Commit Graph

725 Commits

Author SHA1 Message Date
Pablo Carranza Velez
95bbe6ea49 Add a /v1/healthy endpoint that fails if the supervisor is unhealthy, and a HEALTHCHECK command to the Dockerfile that uses it
We add an endpoint to the supervisor API that checks the following conditions to determine whether the supervisor is healthy:
* That the update cycle has run fully, in a time that's less than twice the poll interval. Unless we're downloading an image, in which case
we assume it's healthy (otherwise we'd get into the issue of determining a reasonable timeout for the image download, which is already done in a configurable way with delta options and the like).
* That the current state report to the Resin API hasn't failed more than 3 times. Unless the device has no connectivity, or the connectivity check is disabled, in which case we don't know
if the report failed simply because there's no network.
* That the gosuper component is working (since we periodically hit its API to get the IP addresses, we mark it as not working if this API call fails).

We need this endpoint to be unauthenticated for the docker daemon to be able to hit it (though, as the rest of the API, it is protected with iptables rules).

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-12-11 00:11:56 -08:00
Pablo Carranza Velez
f65822ba94 Use for own instead of _.forEach
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-12-10 21:52:03 -08:00
Pablo Carranza Velez
5a0042c33d Apply config.txt changes when the new config is empty, to fix deleting config.txt values
I realized we're not deleting config.txt entries because the function checked for the values to apply
not to be empty, instead of just checking if the *changes* are empty.

So this closes #450

(Still not a complete solution to config.txt issues, which will come with the multicontainer PR, but at least it's a step forward)

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-12-10 19:09:10 -08:00
Pablo Carranza Velez
e0d1d89419 Filter deviceConfig values that will be stored as current values to only include relevant keys
Otherwise, devices where we update from legacy supervisors might have other keys, like RESIN_SUPERVISOR_DELTA, stored in deviceConfig.values,
causing `_.isEqual(values, targetValues)` to always return false.

Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-12-10 18:54:08 -08:00
Pablo Carranza Velez
c05474b1a9 Always execute special actions if the value stored in memory doesn't match the target. And when storing target values, only store relevant ones
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-12-10 18:48:30 -08:00
Pablo Carranza Velez
8fc1a0935b Avoid stopping the VPN until a remote target state has been fetched, and retry applying config variables when they fail
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-12-08 00:16:34 -08:00
Pablo Carranza Velez
21a9bb4e82 When listenPort is not specified, use 48484 as default
Should only be relevant in really old OS versions, but still this is the correct default.

Fixes #439

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-11-23 14:08:32 -08:00
Pablo Carranza Velez
51d6ab01c9 Avoid an indefinite recursion that grows the call stack when reporting the current state fails
We used to have a recursion based on Promises and Promise.delay, which caused the promise never to resolve
so eventually the stack would be exhausted.

This fixes it by using a simpler way to check if reporting the state is in progress and using a setImmediate to
call applyState outside of the Promise chain.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-11-02 15:54:09 -07:00
Pablo Carranza Velez
20d95ff024 Add whitelist-based filtering to mixpanel events
When sending events to mixpanel, we now use an explicit whitelist for the properties sent with the event, to avoid accidental leakage of any sensitive information.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-31 23:22:38 -07:00
Pablo Carranza Velez
34d37814c9 Tunnel all mixpanel events through the resin API
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-31 23:22:38 -07:00
Pablo Carranza Velez
ecf7e4206c Avoid fetching an image when it might be available or when starting an app because it might not be necessary
This change removes the behavior where we would try to fetch an app image when starting the app. This might cause an unintended
download of an app that is not really needed anymore because we're starting the app on boot and an update cycle would make this image unnecessary.
So now we try to inspect the image, and if this fails we will throw an error, causing the app to be soft-deleted and the next update cycle to properly trigger
a download of whatever image we need from the target state.

We also improve the error catching when fetching an image, to specifically catch an "image not found" error before trying to download - otherwise, any other
random error will cause us to try to download the image again, which will not be a noop if we're using deltas. If there's any other error, the correct behavior
is to throw and retry later.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-30 15:25:49 -07:00
Pablo Carranza Velez
0bc23df8c9 Refactor container cleanup to remove all spurious containers
We change the way container cleanup works so that it compares running
app containers with the container names for the known apps. This allows
the cleanup to effectively delete any spurious/duplicated app containers.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-30 15:25:49 -07:00
Pablo Carranza Velez
bd34a19a79 Use container name instead of id to identify apps, and avoid duplicated containers
By storing the container name before creating the container, we avoid problems
if the supervisor crashes or the device reboots between creating a container and storing its id.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-30 15:25:49 -07:00
Pablo Carranza Velez
c532344dce If a device is already provisioned but the key exchange fails, retry it until it succeeds
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-27 18:40:29 -07:00
Pagan Gazzard
21712ae810 Change the update retry to back off to the standard update check interval
This means that the supervisor will be less aggressive in the case of the api experiencing issues, stopping it from compounding the issue if the api is being overloaded

Change-type: patch
2017-10-24 15:36:43 -07:00
Pablo Carranza Velez
a87c6682a2 Ensure preloaded apps are properly loaded by setting their internal markedForDeletion to false, and run apps that have it set to null
Currently preloaded apps don't run because their markedForDeletion field in the database is null. In this commit we set it to false, and we
also change the startup check to also run any apps that have markedForDeletion as null (which should now never happen, but is still good as a backup
plan in case something else fails and to avoid regressions).

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-23 17:29:41 -07:00
Pablo Carranza Velez
3f198fc6aa Improve the check for when the device has been provisioned but the supervisor doesn't have knowledge of it in its local state
This change improves the check for the DuplicateUuidError that can happen if a device has been provisioned but the API's response hasn't been persisted - the error message
returned from the API has been known to have a few variations (usually an extra dot at the end), so we now use _.startsWith instead of checking for equal strings to make the
supervisor still work under these variations.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-23 17:28:36 -07:00
Pablo Carranza Velez
d98897cdcf Ensure preloaded apps get the deviceApiKey in the env vars, and apps never get the provisioning key, and improve detection of cases when the device has been pre-provisioned
It appears preloaded apps have been getting restarted because the "apiKey" configuration value was only available after provisioning succeeded. This change ensures the
deviceApiKey that the device will use is injected into the env vars of preloaded apps, ensuring the app is not restarted (unless provisioning fails and the uuid and deviceApiKey are
regenerated, but this should be rare).

We also ensure that whenever an app's RESIN_API_KEY env var is populated, it is *always* done with the deviceApiKey and never with the provisioning apiKey.

Closes #457
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-10-23 17:28:17 -07:00
Akis Kesoglou
78f74d757d Delta improvements
- Updates resumable-request to 1.0.1
- Updates docker-progress to 2.0.3
- Removes `DEFAULT_DELTA_APPLY_TIMEOUT`; it’s not needed anymore, docker-delta reliably tracks rsync.
- Properly end the update when applying the delta results in an error.

Change-Type: patch
2017-10-17 10:43:12 +03:00
Pablo Carranza Velez
31d09e70e4 Explicitly define the source for deltas, allow cross-app deltas, and iterate serially through apps when updating
This commit changes the way the source for a delta is determined. We used to do
it by comparing the available tags with the one we want and relying on the format that
includes the app in the image name. Now we explicitly choose a delta source from the previous app
version if we have one, and otherwise use the image from any available app - which will allow us
to have a valid source when moving a device between apps.

For this to work consistently if there's an unexpected reboot, we now avoid deleting an app from the db
until the full update has succeeded. Instead, we mark the app for deletion so that we still have the image stored after the reboot.

This commit also changes a .map to .mapSeries when iterating over appIds for removal/install/update - this avoids parallel treatment
of apps which can cause inconsistencies in the status reported to the API.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-09-14 14:52:06 -07:00
Pablo Carranza Velez
81a6c2f344 Fix problem catching errors when killing a container that doesn't exist
We've been using `.catch Promise.OperationalError, ...` to catch errors when stopping a container and
detecting whether the error means that the container has already been stopped of removed.

Apparently, after the recent dockerode upgrade these errors are not typed as OperationalError anymore, causing error
messages like "No such container: null" when applying an update. This commit makes us catch all errors and check for their statusCode.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-09-05 20:17:43 -07:00
Pablo Carranza Velez
dbb4fd8292 Prefer err.message when reporting errors from dockerode, then err.json and err.reason
Errors from docker-modem that are passed from dockerode can have a "json" or "reason" property,
but that is generally less descriptive than the more standard "message", and can show up in the logs
as `[object Object]`. This commit changes it so that we log err.message if it is non-empty, and otherwise
look for json and reason.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-09-01 15:08:10 -07:00
Akis Kesoglou
a5980918b4 Forward resume options
Change-Type: patch
2017-08-29 00:02:26 +03:00
Akis Kesoglou
52c55a0c1b Apply a default timeout unless one is given 2017-08-09 11:55:22 +03:00
Akis Kesoglou
1412785886 Try to resume the download of a delta if it fails due to flaky network
Applying a delta update consists of two parts:

1. The request to the delta server for the delta payload (an rsync batch file, plus some prepended Docker metadata). The response is a redirect to a URL that contains the delta (currently S3).
2. The request for the actual download of the delta. The response is streamed directly to rsync, which applies it onto the mounted root filesystem of the final image.

The first step may take a while as it may trigger the generation of the delta if the request is the first one for this combination of src/dest image and the images are large. If the request times out, either because of the delta server taking too long to respond or bad network, the Supervisor automatically schedules a retry to be performed after a while.

Currently, similar behaviour applies to the second step as well -- if the request fails, we immediately bail out and the Supervisor schedules a retry of the whole process (i.e. from step 1). But in this case it means we might have downloaded and applied some or most of the delta when a socket timeout occurs causing us to start all over again, wasting time and bandwidth.

This commit splits the process into the two discreet steps and improves the behaviour on the second step. Specifically:

- makes the Supervisor try to resume the delta download request several times before it bails out and starts the process all over again.
- removes arbitrary timeout which applied over the whole process and meant some deltas would never manage to be applied (because of large delta size and low network bandwidth).
- makes sure any launched rsync processes always exit and any opened streams consumed and closed.

Most of the improvements are in the two dependencies linked below -- `resumable-request` and `node-docker-delta` -- and this commit merely combines the updated versions of these modules.

Change-Type: minor
Connects-To: #140
Depends-On: https://github.com/resin-io/node-docker-delta/pull/19
Depends-On: https://github.com/resin-io-modules/resumable-request/pull/2
2017-08-09 11:55:22 +03:00
Pablo Carranza Velez
6f87b1db18 Avoid starting apps on startup if device has to reboot due to a configuration change
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-08-02 20:07:13 -03:00
Pablo Carranza Velez
42ac7487e7 When the device is about to reboot or shutdown, close the API server and avoid applying updates
We mark when the device is rebooting and avoid some steps in the update cycle that change the device
state, similarly to when the device is in local mode, to avoid problems with non-atomic operations.
This doesn't solve *all* the potential scenarios of a reboot happening in the middle of an update, but at least
should prevent the case where we start an app container and reboot the device before saving the containerId, potentially
causing a duplicated container issue.

We also correct the API docs to reflect the 202 response when reboot or shutdown are successful.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-27 20:07:24 -03:00
Pablo Carranza Velez
55ad977ede Avoid unhandled errors when in offline mode due to a missing apiEndpoint
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-27 12:46:14 -03:00
Pablo Carranza Velez
f0344ca4be Do not persist the uuid when in offline mode, so that the supervisor tries to provision if it goes out of offline mode
We used to store the uuid which would cause the supervisor to not attempt a provisioning even if offline mode
was turned off. This was to avoid preloaded apps being reloaded constantly leaving multiple containers.

We now avoid persisting the uuid, so that when the supervisor goes out of offline mode it can provision
without the need to wipe out the db. We avoid the problem with preloaded apps by not loading them
if there's apps already stored on the db.

(In the future, apps in the db will only represent target state and we can make preloaded apps be reloaded on every
start, but for now we can't do it as long as we store the containerId on the db - deleting an app on the db
means losing track of its containerId and therefore leaving an orphaned container)

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-27 12:46:14 -03:00
Pablo Carranza Velez
7aedd7062d Update docker-delta to 1.1.1, docker-toolbelt to 3.0.1, docker-progress to 2.6.0 to add support for deltas and overlay2
This makes the Async suffix for docker functions unnecessary. It also allows us to remove dockerode as an
explicit dependency.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-27 01:48:35 -03:00
Pablo Carranza Velez
279ab60233 Fix the message shown when docker gives a 500 error when starting a container
The test for an exec format error caused a `err.json.trim` is not a function
error so the message shown didn't relate to what the problem actually was.
This makes the test for the exec format error safer.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-26 10:41:25 -03:00
Pablo Carranza Velez
1790939046 Use webpack to join all modules
This saves around 13MB in the resulting uncompressed docker image.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-11 14:01:16 -07:00
Joe Roberts
087e7c3af0
Deprecate edge device type
Change-type: major
2017-07-05 10:20:26 +01:00
Pablo Carranza Velez
8b2138f744 Fix semver comparison for OS version when determining if the device has deviceApiKey support
The current setup would cause the check to always fail - the consequence is not *that* bad since
the provisioning key still gets overwritten, but it's better to delete it if we can.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-07-04 02:56:31 -07:00
Pablo Carranza Velez
928df5b140 Allow registering the deviceApiKey in a non-compatible OS by making the apiKey equal the deviceApiKey, and add an fsync to all config.json writes
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-06-30 18:00:01 -07:00
Pablo Carranza Velez
597a2c6b65 Remove the undocumented and unused sideload and compose APIs
This allows us to also remove a few npm dependencies and the docker compose binary.

Change-Type: major
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-06-26 13:08:52 -07:00
Pablo Carranza Velez
18ca98a2ae Fix provisioning key exchange by passing apikey in the request
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-06-26 07:04:43 -07:00
Pablo Carranza Velez
00b53bd03e When apiEndpoint is not defined, work in offline mode
The supervisor uses an `API_ENDPOINT` environment variable to define what API to register to. Up to now this has been defaulted to `https://api.resin.io`.
(In Resin OS devices this environment variable ultimately comes from config.json).
This commit changes the behavior so that an empty value of that environment variable causes the supervisor to work in "offline mode", i.e. not connected to a remote server.
Basically only preloaded apps and the supervisor API work in this mode.

The config.json `supervisorOfflineMode` field still works for backwards compatibility, but we'll treat it as deprecated and it should be removed eventually.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-06-14 12:57:47 -07:00
Pablo Carranza Velez
1e7bdad7a9 Fix mixpanel initialization when not in offline mode
The logic to disable mixpanel initialization in offline mode was inverted :S causing mixpanel
to *only* be initialized when in offline mode.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-06-14 12:48:29 -07:00
Joe Roberts
d4e3e45e52
Dependent device DB migrations 2017-06-14 09:27:47 +01:00
Joe Roberts
786874dbb6
Update dependent device DB
Change-type: patch
2017-06-14 09:27:47 +01:00
Petros Angelatos
171460041f
enable SSL when connecting to pubnub
Fixes #451

Connected-to: pubnub/javascript#89
Change-Type: patch
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2017-06-13 19:13:09 +03:00
Pablo Carranza Velez
08c5413413 Fix typo in how hostOSVersionPath was camel-cased
This was properly done in the recently added changes in bootstrap.coffee,
but all other references where using "Os" instead of "OS.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-05-11 13:06:38 -07:00
Pablo Carranza Velez
cb0152c5ea Properly handle errors when requesting deltas
When requesting a delta, a `Promise.join` promise chain was producing unhandled
errors since it consisted in a separate promise chain from the parent function which,
was created with `new Promise`. This commit fixes this by creating the new Promise only
when it's needed, avoiding the creation of a separate promise chain.

Closes #432
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-05-08 15:05:42 -07:00
Pablo Carranza Vélez
ac2531368c Merge pull request #427 from resin-io/dont-update-deviceconfig-if-unchanged
Avoid writing target device config to DB if it hasn't changed
2017-04-27 21:18:38 -07:00
Pablo Carranza Velez
c251de1cd3 Only delete the provisioning key if the supervisor is running on an OS that supports using the deviceApiKey
This avoids problems when updating the supervisor on an older OS, where the VPN and other
host services still require config.json to have an apiKey field to authenticate.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-04-27 13:31:25 -07:00
Pablo Carranza Velez
e36fa601ad Avoid writing target device config to DB if it hasn't changed
This helps avoid unnecessary writes to the DB which may cause disk wearout.

We also change the error message in this section to show that the error might have happened
when fetching the device config as much as when setting it.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-04-27 09:42:41 -07:00
Pagan Gazzard
42cd3a6b01 Fix an infinite loop that could happen when trying to bootstrap if the key exchange fails
Change-Type: patch
2017-04-26 13:54:15 -07:00
Pagan Gazzard
89ccb6480d Fix the case of being registered with a version of the cli/sdk that does not support device api keys.
Change-Type: patch
2017-04-26 13:52:43 -07:00
Pagan Gazzard
d31ee452d0 Deduplicate the device fetching logic 2017-04-24 12:09:50 -07:00
Pagan Gazzard
1002629a5e Improve key exchange by first checking if an existing device api key is valid. 2017-04-22 15:17:00 -07:00
Pagan Gazzard
477184d72d Add handling for duplicate UUIDs and key exchanging for old user-api-keys
Change-Type: minor
2017-04-20 21:37:27 -07:00
Pagan Gazzard
03ec97ab8d Change to the new device registration method to exchange our provisioning key with a dedicated api key for the device.
Change-Type: minor
2017-04-20 21:37:27 -07:00
Pablo Carranza Velez
4d322c72a0 Issue #420: Avoid supervisor crash without connection by properly memoizing promise-returning functions
device.getID caused a fatal error when connection was down, as the memoization with `promise: true` throws
synchronously. Changing memoizee to use `promise: 'then'` makes the memoization work as expected.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-04-05 14:51:26 -07:00
Pablo Carranza Velez
0e288d75ab Report the OS variant as a separate field and not as part of the OS version
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-04-03 09:32:28 -07:00
Pablo Carranza Velez
99c9b96ed3 Issue #413: Fix an error applying the connectivity check config var
There was a ReferenceError from a leftover variable, introduced in #398.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-30 12:04:38 -03:00
Pablo Carranza Velez
5412e766da Issue #410: Cleanup images before running an update, preserving the ones that will be used in the target state
We add an extra image/container cleanup before applying updates, allowing any unwanted images to be deleted.
When doing this, we take care not to delete images that will be used when the target state is applied.

This prevents the problem of stale images being stored while the update lock is set, potentially
leaving the device out of space.

Running the cleanup *before* applying the update ensures that only one target image is downloaded: if a stale one
had been downloaded previously, it will be deleted before starting the update for the new one. This can have a slight
impact on delta performance, since the delta is potentially done from an older (and more different) version of the app,
but can have a big impact on storage usage, as not doing this would duplicate the required free storage space when
the update lock is set.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-29 16:50:12 -03:00
Andreas Fitzek
55a1742b1f Merge branch 'master' into 404_authentication_for_registry_and_delta 2017-03-29 11:08:03 +02:00
Andreas Fitzek
ff01d27b7a Authentication credentials for registry and delta server
Hand over authentication credentials to the docker engine
Fetch an access token from the API if possible and hand it over to the delta server

Change-Type: minor
Signed-off-by: Andreas Fitzek <andreas@resin.io>
2017-03-29 01:11:16 +02:00
Pablo Carranza Velez
147abe8a76 Issue #402: Ensure that app configs are non-null and valid json objects
This prevents duplicated containers when updating from older supervisors before the config column
was introduced.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-28 14:13:22 -03:00
Pablo Carranza Velez
8c59c2d768 Report OS variant to the API together with the OS version
Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-23 20:29:52 -03:00
Pablo Carranza Velez
b2a2ca0246 Issue #230: Add a custom User-Agent header to all requests
Header is in the format Supervisor/X.Y.Z (Linux; Resin OS v2.A.B.revC; Dev) - omitting any fields
that are not available depending on the OS.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-23 20:28:50 -03:00
Pablo Carranza Velez
c2fe956967 Issue #396: Log when we're rebooting due to a device config change
We also add a 1s delay before rebooting to ensure logs are published.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-10 01:19:56 +02:00
Pablo Carranza Velez
27690e0c30 Issue #20: Change the update lock to a temporary filesystem
The lock is now located at `/tmp/resin-supervisor/<appId>/` on the host, and `/tmp/resin/`
on the user container. The old lock location is supported only in Resin OS 1.X (and both locks are
taken in that case).

This fixes the race condition when the app is started before the supervisor, and takes a lock that is
cleared on supervisor startup.

Change-Type: major
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-10 01:19:35 +02:00
Pablo Carranza Velez
208b799c4b Make local mode only work in development OS, and make it remove app containers and allow unauthenticated API requests
Local mode makes the API accept unauthenticated requests.
Local mode now also removes app containers when stopping them.

Local mode only works on a host OS that has `VARIANT_ID = "dev"` in /etc/os-release.

Also add more explicit logging when stopping an app and it was already stopped
or the container was already removed.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-10 01:19:19 +02:00
Pablo Carranza Velez
72f6b2cea5 Restore default value when clearing a special action config variable
Up to now we've only been running the "special actions" (like vpn on/off, logs on/off)
when the target state includes a current value for the corresponding config variable.
We now also check if there was a *previous* value, and in that case also call the action function.
These functions are prepared to reset to a default when they're called with an undefined value.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-10 01:19:19 +02:00
Pablo Carranza Velez
538e384442 Allow all config variables to take truthy or falsy values
Config variables now use a checkTruthy validation function,
and can be "1", "on", "true" or true to be considered true, or
"0", "off", "false" or false to be considered false.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-10 01:19:19 +02:00
Pablo Carranza Velez
9ae4f02bc5 Allow setting the supervisor to a "local mode" which stops apps and prevents cleanup
A RESIN_SUPERVISOR_LOCAL_MODE variable is introduced. When this variable is "1", all apps
are stopped and the update cycle stops executing changes other than deviceConfig changes
and the proxyvisor.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-10 01:19:19 +02:00
Pablo Carranza Velez
9d36064bdb Quick fix: unindent the definition for dockerUtils.createContainer
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-09 08:57:26 -03:00
Pablo Carranza Velez
b6206f9012 Issues #23 and #236: Use docker logs to get all logs from the container, including those before supervisor start
We've been using docker attach, which only gives us the logs since we attach. This change allows getting the
full logs from the beginning.
We also use the timestamps that come with the logs from docker, as they will be more precise and are more relevant now
that we're getting previous logs from history.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-07 17:26:38 +02:00
Pablo Carranza Velez
b64ed9568c Issues #389 and #390: Remove /host_run/dbus and /host/var/lib/connman bind mounts for non-ResinOS-1.X devices
On ResinOS 2.X the default mounts should not include the previously deprecated host_run, and there's no connman which makes the connman mount confusing.
This is a breaking change as it is not backwards-compatible on non-ResinOS instances of the supervisor.

Change-Type: major
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-07 17:26:23 +02:00
Pablo Carranza Velez
f7c702b845 Issue #386: Allow forcing updates when an update was already scheduled
The logic for updateStatus.forceNext is changed so that its value is checked when the scheduled update is run, instead
of when the update is scheduled. And when an update is already scheduled and a new request comes in,
we mark forceNext as true if the new request requires a force update.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-03-07 17:06:10 +02:00
Pablo Carranza Velez
e8fbadb8d6 Issue #381: Set target deviceConfig values from preloaded apps
Also split out deviceConfig set and get to a separate module to avoid circular dependencies.

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-01-19 13:56:20 -03:00
Pablo Carranza Velez
0d870954ef Issue #382: Validate delta timeout variables
Also take validation functions into a module, and use that in all cases where
we need to check for an integer or string.

Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-01-18 12:28:24 -03:00
Pablo Carranza Vélez
0e76b540ea Merge pull request #379 from resin-io/378-delta-timeout
Increase delta timeouts, and provide nicer message when the delta server times out
2017-01-17 18:49:19 -03:00
Pablo Carranza Velez
9c8ac58128 Issue #378: Increase delta timeouts (to avoid ESOCKETTIMEOUT errors), make them configurable, and provide nicer message when the delta server times out
Current delta timeouts are too limiting, so we increase the request timeout to 30 minutes which is big enough that
the server will time out first and we can provide a nice message letting the user know we'll retry; and we increase
the total timeout to 24 hours to account for really big deltas over slower connections (the rsync calls will time out anyways
if something else goes wrong, as they have a 5 minute I/O timeout).

The timeouts are now configurable with the RESIN_SUPERVISOR_DELTA_REQUEST_TIMEOUT and RESIN_SUPERVISOR_DELTA_TOTAL_TIMEOUT
configuration variables.

Change-Type: minor
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-01-17 14:21:10 -03:00
Pablo Carranza Vélez
6ab2b45104 Merge pull request #370 from resin-io/359-kmod-only-in-resinos1
[Breaking] Do not bind mount kmod if the host is not Resin OS 1.X
2017-01-16 12:51:08 -03:00
Pablo Carranza Velez
f8d3ea1a22 Add a delay between successive updates of device state to the API
We add a 1s delay between requests to the API to apply state changes,
as this will throttle it to a point that it has a reasonable rate while
preventing too many unnecessary requests to the API.

Closes #375

Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-01-12 15:57:09 -03:00
Pablo Carranza Velez
458add1759 Do not bind mount kmod if the host is not Resin OS 1.X
Resin OS 2.X removes the use of compressed modules, which was the initial
motivation for us to bind mount kmod into user containers (as Debian distros
don't include support for compressed modules).

This is a breaking change, but we still keep bind mounting on devices that are
on 1.X to ensure we don't break apps currently relying on the feature.

Implementation note: some functions in device.coffee have been refactored to
extract (DRY) a memoization procedure for Promise-returning functions.
`device.getOSVersion()` now also memoizes its result.

Change-Type: major
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2017-01-04 18:48:45 -03:00
Pablo Carranza Velez
c67977cbed Fix error applying device configuration because deviceConfig table is empty
If there's no entries in deviceConfig table, always create one.

Avoids problems if the supervisor is stopped while running the db initialization
(deviceConfig gets created but not populated).

Change-Type: patch
Signed-off-by: Pablo Carranza Velez <pablo@resin.io>
2016-12-20 03:01:55 -03:00
Pablo Carranza Velez
fefb1e6928 Fallback to DROP when iptables REJECT is not available
Using REJECT allows better feedback for legitimate users while providing the same level
of security than drop (see http://www.chiark.greenend.org.uk/~peterb/network/drop-vs-reject).

But some hosts don't have REJECT support in the kernel config, so in that case we fall back to DROP.
2016-12-01 11:18:06 -03:00
Pagan Gazzard
01cd0cbc5a Fix an error when trying to call logSystemEvent with an undefined app 2016-11-03 19:43:15 +00:00
Pablo Carranza Velez
5bcff712dc Provide a better error message when app is not found for purging 2016-11-01 12:20:51 +00:00
Pablo Carranza Velez
0e2710152b Only iterate through remote apps to set device config 2016-10-31 21:41:35 +00:00
Pablo Carranza Velez
9af4ed0397 Properly delete dependent apps and their corresponding devices 2016-10-31 03:05:45 +00:00
Pablo Carranza Vélez
fe68b27acb Merge pull request #336 from resin-io/request-timeout
Add Promise timeouts to all external requests
2016-10-30 21:47:21 -03:00
Pablo Carranza Velez
ac02d50715 Improvements in container create/start:
* Add HostConfig in container create instead of start
* Make it clear in logs when container was already running
2016-10-29 10:20:44 -03:00
Pablo Carranza Velez
c06e047fba Add Promise timeouts to all external requests 2016-10-28 15:12:08 -03:00
Pablo Carranza Velez
3325ff47d4 Stop all apps before rebooting or shutting down 2016-10-27 20:18:30 -03:00
Pablo Carranza Velez
6077f1add4 Update request-progress to v2.0.1 2016-10-25 16:29:53 -03:00
Pablo Carranza Velez
e9e1a0b277 Use multiArgs to promisify gosuper requests
With the bluebird update to v3, all requests to gosuper (most notably, getting the IP addresses) got broken as we use .spread, which requires the Promise to fulfill with an array. So we need to add multiArgs so that getAsync and postAsync return an array.
2016-10-24 16:26:00 -03:00
Pablo Carranza Velez
d3761a699b Also make it explicit in mixpanel events when it's a full image download 2016-10-24 16:11:47 -03:00
Pablo Carranza Velez
43c1b2f92c Log whether deltas are being used when downloading an app 2016-10-23 20:18:20 -03:00
Pagan Gazzard
4ed64536ec Fix multiple update loops appearing after a long period of updates failing. 2016-10-21 16:03:24 -07:00
Pablo Carranza Velez
70dc744886 Avoid restarting the app if the device name changes 2016-10-21 18:40:03 -03:00
Pablo Carranza Velez
d6aead1bad AUFS support and dependent app assets improvement:
* Use appId in dependent app assets tar path, and only create the tar if it doesn't exist
* Support AUFS by upgrading node-docker-delta to 1.0.0 and docker-toolbelt to 1.3.0
2016-10-21 16:37:57 -03:00
Pablo Carranza Velez
8361a533a1 Send the uuid as distinct_id for mixpanel events 2016-10-21 16:36:11 -03:00
Pablo Carranza Velez
7bb3931f2c Properly set device name, and set undefined arguments to setConfig as null 2016-10-13 15:13:47 -03:00
Pagan Gazzard
158ce2810c Update knex to ~0.12.3 2016-10-11 12:04:28 -07:00
Pablo Carranza Velez
72d0401403 Do not use parsed JSON to compare dep. device state 2016-10-11 12:13:14 -03:00
Pablo Carranza Velez
6feba39948 Fix docker utils getImageEnv by correctly parsing the returned array 2016-10-10 21:58:20 +00:00
Pagan Gazzard
969d714baf Update to bluebird 3 2016-10-10 12:49:54 -07:00
Pablo Carranza Velez
feb97539ef Improvements in proxyvisor:
* Better parameter handling in PUT /v1/devices/:uuid
* An update hook response of 200 will cause the proxyvisor to stop pinging the hook
* Allow deleting dependent apps and devices
* Implement delete dependent device hook
* Omit some fields when responding with a device object
2016-10-10 18:16:16 +00:00
Pablo Carranza Velez
ceb5016fc3 Add validation to dependent device provisioning 2016-10-08 20:42:50 +00:00
Petros Angelatos
04edb15819 remove resolv.conf bind mount
connects to #310

Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2016-10-07 16:36:18 -07:00
Page-
3a2ec489b8 Merge pull request #303 from resin-io/cleanup
Remove unnecessary Promise.all
2016-10-06 14:59:29 -07:00
Pagan Gazzard
81cb59262f Remove unnecessary Promise.all 2016-10-05 18:31:29 -07:00
Pablo Carranza Velez
c4e5d7afca Improvements on config and dependent device handling:
* Store config vars when there's nothing else to update
* Do not mark an update as failed if the hook failed
* When hitting the dependent devices hook, send appId as int
2016-10-05 23:21:29 +00:00
Pagan Gazzard
5c10644df7 Update to lodash 4 2016-10-05 23:03:12 +00:00
Pablo Carranza Velez
4785437ba8 Fixes in app restart behavior:
* Compare config vars to trigger an app restart
* In delete-then-download, only delete when a download is needed
2016-10-05 19:45:18 +00:00
Pablo Carranza Velez
503e043c4c In cleanup, normalize all image tags for comparison 2016-10-04 17:48:11 -03:00
Pablo Carranza Velez
ddaa9f12db Use getRegistryAndName from docker-toolbelt 1.2.0 2016-10-04 14:43:45 -03:00
Pagan Gazzard
19db0e78e0 Switch to v2 api to be able to set is_online 2016-09-30 23:40:03 -03:00
Pablo Carranza Velez
a6f2ff074c Dependent devices, state endpoint, extra env vars and deviceConfig:
* Implement proxyvisor API with dependent device handling
* Use the state endpoint from the API to get the full device state
* Add a deviceConfig db table to store host config separately, and allow deleting config.txt entries
* Expose RESIN_APP_NAME, RESIN_APP_RELEASE, RESIN_DEVICE_NAME_AT_INIT, RESIN_DEVICE_TYPE and RESIN_HOST_OS_VERSION env vars
* Add missing error handler on a stream in docker-utils
2016-09-30 23:40:03 -03:00
Pablo Carranza Velez
e7acff0bcf On cleanup, force removal for images and containers, and remove container volumes 2016-09-29 19:34:19 -03:00
Pablo Carranza Velez
f385fe6bcc Add system logs for Shutdown, Reboot and Purge 2016-09-28 03:32:38 +00:00
Pablo Carranza Velez
4a99fd8803 Implement delete-then-download update strategy 2016-09-26 18:16:01 +00:00
Kostas Lekkas
05690a81dc typo: fix startAppError message 2016-09-20 11:35:28 +03:00
Pablo Carranza Velez
16e2ec286e DRY up calls to gosuper API, and use empty Host header 2016-09-13 16:52:25 -03:00
Praneeth Bodduluri
2cc4b0fb46 Add iptables rules to allow resin-vpn named interface to be used by VPN 2016-09-09 17:41:35 +05:30
Alexios Theodoros Brezas
12a4560518 Catch exec format error and provide friendlier message 2016-09-05 18:22:20 +00:00
Theodor Gherzan
32bf433af1 device.coffee: Remove hardcode of resin-boot partitions's mount point
Signed-off-by: Theodor Gherzan <theodor@gherzan.ro>
2016-09-02 19:55:01 +00:00
Pablo Carranza Velez
ec178f7a7f Use a more conservative message size, and properly account for URI encoding 2016-08-31 16:28:42 +00:00
Pablo Carranza Velez
78b4570b93 Allow storing several messages, will allow us to withstand log bursts better
Also, send a warning message when we start dropping logs.
2016-08-29 19:03:06 -03:00
Pablo Carranza Velez
a8dd29cd82 Change the logger to send at a specific interval and with a different message format
Log messages to PubNub are now an array instead of an object.
Each element of the array is an object with m (message), t (timestamp) and s (isSystem, optional) attributes.
Logs are sent at a specific interval (110ms, fit with some margin to PubNub's approximated 10 messages/s limit), and truncated to PubNub's 32KB limit.
2016-08-29 19:03:06 -03:00
Pablo Carranza Velez
1eb63366ee Allow using an HTTP header for auth 2016-08-16 20:39:55 +00:00
Pablo Carranza Velez
145d124410 Check if rules exist before adding them 2016-08-16 09:30:38 -03:00
Pablo Carranza Velez
c4ea2c77a0 Add iptables rules to block requests to the supervisor API from all interfaces except vpn, docker and local 2016-08-15 18:02:36 -03:00
Petros Angelatos
dd06f993ce bootstrap: if offlineMode is enabled, persist only the uuid
If we don't persist the uuid then every time the supervisor starts it
will think it's a new device. This triggers a wipe of the local state
and also a re-load of the preloaded apps. This in turn causes multiple
instances of the preloaded apps to be left running.

Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2016-08-02 23:48:13 -07:00
Petros Angelatos
5ee15e664e utils: allow specifying links in compose files
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2016-07-28 17:45:16 -07:00
Petros Angelatos
b708f05476 utils: sort compose options
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2016-07-28 17:43:26 -07:00
Petros Angelatos
eb09713391 Merge pull request #216 from resin-io/215-improve-containers-api
Improve containers API
2016-07-26 20:52:56 -07:00
Petros Angelatos
66fe7fc30c logger: empty the publish queue if in offline mode
Signed-off-by: Petros Angelatos <petrosagg@gmail.com>
2016-07-26 14:04:51 -07:00
Pablo Carranza Velez
98d9aca92d Allow the supervisor to work in offline mode
A supervisorOfflineMode true-ish attribute in config.json will cause that:
* If unprovisioned, the supervisor won't try to provision on Resin
* The update cycle will not start as the device won't consider itself provisioned
* Logs will not be sent to pubnub
* Mixpanel events won't be tracked
* The device state won't be updated to the Resin API

This change will also make the Supervisor API work with an unprovisioned device.
2016-07-23 14:04:24 +00:00
Pablo Carranza Velez
02e111ff62 Allow only the options that we know can be supported 2016-07-22 23:28:28 -03:00
Pablo Carranza Velez
4db78b9743 Allow purging and deleting a container from the DB with a purge option 2016-07-22 23:17:25 -03:00
Pablo Carranza Velez
0b4f50d207 Avoid creating duplicate entries in the image table 2016-07-22 23:17:25 -03:00
Pablo Carranza Velez
1d16941a2d Fix cleanup of official images, and allow passing Name in container options 2016-07-22 23:17:25 -03:00
Pablo Carranza Velez
e41ebbb52b Add validation for options when creating and starting containers 2016-07-22 23:17:25 -03:00
Pablo Carranza Velez
54288f036a Improve the docker compose API
- Validate the options in the YAML file
- Define bind mounts for each service as in Resin apps
- Keep the modified compose file inside the supervisor's /data folder
- Fix error reporting in the first stage of "up"
2016-07-22 23:17:25 -03:00
Pablo Carranza Velez
b97fe634d5 Add default binds to containers created with API, add /v1/containers/update endpoint, and add a /data bind with an internal id 2016-07-22 23:17:25 -03:00
Kostas Lekkas
761a0cbd82 Fix double-printed logs after container restart 2016-07-21 22:39:19 +03:00
Pagan Gazzard
8715534d84 Run the linting automatically as part of the jenkins build. 2016-07-19 14:37:46 -07:00
Pablo Carranza Velez
0609619863 Do not bind mount /run/dbus to /run/dbus 2016-07-19 02:13:34 +00:00
Pablo Carranza Velez
f5b0a4e7e7 Default to not bind mounting kmod if container distro can't be found 2016-07-18 16:49:45 +00:00
Pablo Carranza Velez
102eb460db Use log-timestamp to add timestamps to logs 2016-07-18 14:01:16 +00:00
Pablo Carranza Velez
5f926faa70 Bind mount kmod if the container is debian or raspbian
Use docker-toolbelt module.
The bind mount is read-only.
2016-07-15 20:46:09 +00:00
Pablo Carranza Vélez
08d74b578b Fix preloaded apps by passing appId to extendEnvVars 2016-07-06 17:56:51 -03:00
Pagan Gazzard
6cb4b090c5 Rename pullImage to pullAndProtectImage to make it a bit clearer that it isn't a simple pull 2016-06-24 21:08:47 +00:00
Pagan Gazzard
707ed7e1f6 Deduplicate compose command running logic. 2016-06-24 21:08:47 +00:00