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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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>
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.
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.
* 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
* 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
* 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
* 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
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.
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>
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.
- 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"
Allow users to set container restart policy using environment variables.
RESIN_APP_RESTART_POLICY sets the name of the policy, and
if policy is "on-failure", optionally, RESIN_APP_RESTART_RETRIES
sets the maximum number of retries.
More information on docker docs:
https://docs.docker.com/engine/reference/run/#restart-policies-restart
One major change we introduce here is that the default policy is set
to always while we used to have the default "no".
We validate the arguments and pass retries parameter only for the case
of "on-failure" as specified in Docker API as of v1.19.
We could let docker handle the arguments directly, gaining
forwards-compatibility with any new features, but I opted
for an implementation that is as well-defined as possible.
Docker 1.10 sends containerInfo.Image without the ":latest", so
the image name doesn't match the app's imageId.
This fix first splits the image name into repo and tag and then rebuilds
it to include ":latest" when appropriate. Should avoid removing containers
when using resin-sync.
This allows application containers to interface with host connman.
Host /var/lib/connman is bind mounted to /host_var/lib/connman to avoid
collisions with connman installations inside the container.
* On handover, fetch old app from DB before starting the new app (and overwriting the DB record)
* Tidy up the logging
* Fix waitToKill so that it actually works
* Several other fixups