Commit Graph

260 Commits

Author SHA1 Message Date
Matthew Heon 77f9234513 Ignore ENOENT on umount of SHM
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-09-06 10:25:53 -04:00
Matthew Heon de9a394fcf Correctly report errors on unmounting SHM
When we fail to remove a container's SHM, that's an error, and we
need to report it as such. This may be part of our lingering
storage woes.

Also, remove MNT_DETACH. It may be another cause of the storage
removal failures.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-09-05 17:12:27 -04:00
Matthew Heon a760e325f3 Add ability for volumes with options to mount/umount
When volume options and the local volume driver are specified,
the volume is intended to be mounted using the 'mount' command.
Supported options will be used to volume the volume before the
first container using it starts, and unmount the volume after the
last container using it dies.

This should work for any local filesystem, though at present I've
only tested with tmpfs and btrfs.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-09-05 17:12:27 -04:00
baude 8818e358bf handle dns response from cni
when cni returns a list of dns servers, we should add them under the
right conditions.  the defined conditions are as follows:

- if the user provides dns, it and only it are added.
- if not above and you get a cni name server, it is added and a
forwarding dns instance is created for what was in resolv.conf.
- if not either above, the entries from the host's resolv.conf are used.
Signed-off-by: baude <bbaude@redhat.com>

Signed-off-by: baude <bbaude@redhat.com>
2019-09-03 10:10:05 -05:00
Giuseppe Scrivano 69727abdf6
cgroup: fix regression when running systemd
commit 223fe64dc0 introduced the
regression.

When running on cgroups v1, bind mount only /sys/fs/cgroup/systemd as
rw, as the code did earlier.

Also, simplify the rootless code as it doesn't require any special
handling when using --systemd.

Closes: https://bugzilla.redhat.com/show_bug.cgi?id=1737554

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-08-06 19:46:34 +02:00
baude 97b84dedf3 Revert "rootless: Rearrange setup of rootless containers"
This reverts commit 80dcd4bebc.

Signed-off-by: baude <bbaude@redhat.com>
2019-08-06 09:51:38 -05:00
OpenShift Merge Robot 337358ae63
Merge pull request #3690 from adrianreber/ignore-static-ip
restore: added --ignore-static-ip option
2019-08-05 16:11:50 +02:00
OpenShift Merge Robot e2f38cdaa4
Merge pull request #3310 from gabibeyer/rootlessKata
rootless: Rearrange setup of rootless containers ***CIRRUS: TEST IMAGES***
2019-08-05 14:26:04 +02:00
Adrian Reber c23b92b409
restore: added --ignore-static-ip option
If a container is restored multiple times from an exported checkpoint
with the help of '--import --name', the restore will fail if during
'podman run' a static container IP was set with '--ip'. The user can
tell the restore process to ignore the static IP with
'--ignore-static-ip'.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-08-02 10:10:54 +02:00
OpenShift Merge Robot 5056964d09
Merge pull request #3677 from giuseppe/systemd-cgroupsv2
systemd, cgroupsv2: not bind mount /sys/fs/cgroup/systemd
2019-08-01 11:35:20 +02:00
Giuseppe Scrivano 223fe64dc0
systemd, cgroupsv2: not bind mount /sys/fs/cgroup/systemd
when running on a cgroups v2 system, do not bind mount
the named hierarchy /sys/fs/cgroup/systemd as it doesn't exist
anymore.  Instead bind mount the entire /sys/fs/cgroup.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-08-01 07:31:06 +02:00
Gabi Beyer 80dcd4bebc rootless: Rearrange setup of rootless containers
In order to run Podman with VM-based runtimes unprivileged, the
network must be set up prior to the container creation. Therefore
this commit modifies Podman to run rootless containers by:
  1. create a network namespace
  2. pass the netns persistent mount path to the slirp4netns
     to create the tap inferface
  3. pass the netns path to the OCI spec, so the runtime can
     enter the netns

Closes #2897

Signed-off-by: Gabi Beyer <gabrielle.n.beyer@intel.com>
2019-07-30 23:28:52 +00:00
Daniel J Walsh 141c7a5165
Vendor in buildah 1.9.2
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-07-30 16:48:18 -04:00
Giuseppe Scrivano 1d72f651e4
podman: support --userns=ns|container
allow to join the user namespace of another container.

Closes: https://github.com/containers/libpod/issues/3629

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-07-25 23:04:55 +02:00
Peter Hunt a1a79c08b7 Implement conmon exec
This includes:
	Implement exec -i and fix some typos in description of -i docs
	pass failed runtime status to caller
	Add resize handling for a terminal connection
	Customize exec systemd-cgroup slice
	fix healthcheck
	fix top
	add --detach-keys
	Implement podman-remote exec (jhonce)
	* Cleanup some orphaned code (jhonce)
	adapt remote exec for conmon exec (pehunt)
	Fix healthcheck and exec to match docs
		Introduce two new OCIRuntime errors to more comprehensively describe situations in which the runtime can error
		Use these different errors in branching for exit code in healthcheck and exec
	Set conmon to use new api version

Signed-off-by: Jhon Honce <jhonce@redhat.com>

Signed-off-by: Peter Hunt <pehunt@redhat.com>
2019-07-22 15:57:23 -04:00
baude db826d5d75 golangci-lint round #3
this is the third round of preparing to use the golangci-lint on our
code base.

Signed-off-by: baude <bbaude@redhat.com>
2019-07-21 14:22:39 -05:00
Adrian Reber 05549e8b29
Add --ignore-rootfs option for checkpoint/restore
The newly added functionality to include the container's root
file-system changes into the checkpoint archive can now be explicitly
disabled. Either during checkpoint or during restore.

If a container changes a lot of files during its runtime it might be
more effective to migrated the root file-system changes in some other
way and to not needlessly increase the size of the checkpoint archive.

If a checkpoint archive does not contain the root file-system changes
information it will automatically be skipped. If the root file-system
changes are part of the checkpoint archive it is also possible to tell
Podman to ignore these changes.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-07-11 14:43:35 +02:00
Adrian Reber 217f2e77f8
Include root file-system changes in container migration
One of the last limitations when migrating a container using Podman's
'podman container checkpoint --export=/path/to/archive.tar.gz' was
that it was necessary to manually handle changes to the container's root
file-system. The recommendation was to mount everything as --tmpfs where
the root file-system was changed.

This extends the checkpoint export functionality to also include all
changes to the root file-system in the checkpoint archive. The
checkpoint archive now includes a tarstream of the result from 'podman
diff'. This tarstream will be applied to the restored container before
restoring the container.

With this any container can now be migrated, even it there are changes
to the root file-system.

There was some discussion before implementing this to base the root
file-system migration on 'podman commit', but it seemed wrong to do
a 'podman commit' before the migration as that would change the parent
layer the restored container is referencing. Probably not really a
problem, but it would have meant that a migrated container will always
reference another storage top layer than it used to reference during
initial creation.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-07-11 14:43:34 +02:00
Adrian Reber f187bab497
Correctly set FinishedTime for checkpointed container
During 'podman container checkpoint' the finished time was not set. This
resulted in a strange container status after checkpointing:

 Exited (0) 292 years ago

During checkpointing FinishedTime is now set to time.now().

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-07-11 07:35:38 +02:00
baude 1d36501f96 code cleanup
clean up code identified as problematic by golands inspection

Signed-off-by: baude <bbaude@redhat.com>
2019-07-08 09:18:11 -05:00
baude 8561b99644 libpod removal from main (phase 2)
this is phase 2 for the removal of libpod from main.

Signed-off-by: baude <bbaude@redhat.com>
2019-06-27 07:56:24 -05:00
Giuseppe Scrivano e27fef335a
stats: fix cgroup path for rootless containers
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-06-26 13:17:06 +02:00
baude dd81a44ccf remove libpod from main
the compilation demands of having libpod in main is a burden for the
remote client compilations.  to combat this, we should move the use of
libpod structs, vars, constants, and functions into the adapter code
where it will only be compiled by the local client.

this should result in cleaner code organization and smaller binaries. it
should also help if we ever need to compile the remote client on
non-Linux operating systems natively (not cross-compiled).

Signed-off-by: baude <bbaude@redhat.com>
2019-06-25 13:51:24 -05:00
Giuseppe Scrivano bd5e113b71
rootless: add an entry to /etc/hosts when using slirp4netns
Closes: https://github.com/containers/libpod/issues/3405

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-06-24 10:12:33 +02:00
Matthew Heon 92bae8d308 Begin adding support for multiple OCI runtimes
Allow Podman containers to request to use a specific OCI runtime
if multiple runtimes are configured. This is the first step to
properly supporting containers in a multi-runtime environment.

The biggest changes are that all OCI runtimes are now initialized
when Podman creates its runtime, and containers now use the
runtime requested in their configuration (instead of always the
default runtime).

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-06-19 17:08:43 -04:00
OpenShift Merge Robot bce4a93575
Merge pull request #3297 from rhatdan/systemd
Accidently removed /run/lock from systemd mounts
2019-06-17 21:26:33 +02:00
Giuseppe Scrivano 0e34d9093e
rootless: use the slirp4netns builtin DNS first
When using slirp4netns, be sure the built-in DNS server is the first
one to be used.

Closes: https://github.com/containers/libpod/issues/3277

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-06-12 10:29:57 +02:00
Daniel J Walsh 805d1d96fa
Accidently removed /run/lock from systemd mounts
This is blowing up systemd containers on Ubuntu.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-06-11 07:54:55 -04:00
Adrian Reber bef83c42ea
migration: add possibility to restore a container with a new name
The option to restore a container from an external checkpoint archive
(podman container restore -i /tmp/checkpoint.tar.gz) restores a
container with the same name and same ID as id had before checkpointing.

This commit adds the option '--name,-n' to 'podman container restore'.
With this option the restored container gets the name specified after
'--name,-n' and a new ID. This way it is possible to restore one
container multiple times.

If a container is restored with a new name Podman will not try to
request the same IP address for the container as it had during
checkpointing. This implicitly assumes that if a container is restored
from a checkpoint archive with a different name, that it will be
restored multiple times and restoring a container multiple times with
the same IP address will fail as each IP address can only be used once.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-06-04 14:02:51 +02:00
Adrian Reber 0028578b43
Added support to migrate containers
This commit adds an option to the checkpoint command to export a
checkpoint into a tar.gz file as well as importing a checkpoint tar.gz
file during restore. With all checkpoint artifacts in one file it is
possible to easily transfer a checkpoint and thus enabling container
migration in Podman. With the following steps it is possible to migrate
a running container from one system (source) to another (destination).

 Source system:
  * podman container checkpoint -l -e /tmp/checkpoint.tar.gz
  * scp /tmp/checkpoint.tar.gz destination:/tmp

 Destination system:
  * podman pull 'container-image-as-on-source-system'
  * podman container restore -i /tmp/checkpoint.tar.gz

The exported tar.gz file contains the checkpoint image as created by
CRIU and a few additional JSON files describing the state of the
checkpointed container.

Now the container is running on the destination system with the same
state just as during checkpointing. If the container is kept running
on the source system with the checkpoint flag '-R', the result will be
that the same container is running on two different hosts.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-06-03 22:05:12 +02:00
Adrian Reber a05cfd24bb
Added helper functions for container migration
This adds a couple of function in structure members needed in the next
commit to make container migration actually work. This just splits of
the function which are not modifying existing code.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-06-03 22:05:12 +02:00
Valentin Rothberg fe928c6b42 apparmor: don't load/set profile in privileged mode
Commit 27f9e23a0b already prevents setting the profile when creating
the spec but we also need to avoid loading and setting the profile when
creating the container.

Fixes: #3112
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2019-05-23 13:17:30 +02:00
Daniel J Walsh 3a4be4b66c
Add --read-only-tmpfs options
The --read-only-tmpfs option caused podman to mount tmpfs on /run, /tmp, /var/tmp
if the container is running int read-only mode.

The default is true, so you would need to execute a command like

--read-only --read-only-tmpfs=false to turn off this behaviour.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-04-26 12:29:10 -04:00
Adrian Reber 86987b8038 Use the same SELinux label for CRIU log files
The SELinux label for the CRIU dump.log was explicitly set in Podman.
The label for the restore.log, however, not. This just moves the code
to label the log file into a function and calls that functions during
checkpoint and restore.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-04-12 15:17:03 +02:00
Jhon Honce 09ff62429a Implement podman-remote rm
* refactor command output to use one function
* Add new worker pool parallel operations
* Implement podman-remote umount
* Refactored podman wait to use printCmdOutput()

Signed-off-by: Jhon Honce <jhonce@redhat.com>
2019-04-09 11:55:26 -07:00
Matthew Heon d245c6df29 Switch Libpod over to new explicit named volumes
This swaps the previous handling (parse all volume mounts on the
container and look for ones that might refer to named volumes)
for the new, explicit named volume lists stored per-container.

It also deprecates force-removing volumes that are in use. I
don't know how we want to handle this yet, but leaving containers
that depend on a volume that no longer exists is definitely not
correct.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-04-04 12:26:29 -04:00
Giuseppe Scrivano 849548ffb8
userns: do not use an intermediate mount namespace
We have an issue in the current implementation where the cleanup
process is not able to umount the storage as it is running in a
separate namespace.

Simplify the implementation for user namespaces by not using an
intermediate mount namespace.  For doing it, we need to relax the
permissions on the parent directories and allow browsing
them. Containers that are running without a user namespace, will still
maintain mode 0700 on their directory.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-03-29 14:04:44 +01:00
Valentin Rothberg a5443a532b vendor buildah, image, storage, cni
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2019-03-28 15:12:26 +01:00
Matthew Heon 0cd92eae65 Resolve review comments
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-03-27 10:12:18 -04:00
Matthew Heon 72f03f0c25 Add support to disable creation of network config files
Specifically, we want to be able to specify whether resolv.conf
and /etc/hosts will be create and bind-mounted into the
container.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-03-27 10:12:18 -04:00
Giuseppe Scrivano 7f6f2f3f4a
userns: use the intermediate mountns for volumes
when --uidmap is used, the user won't be able to access
/var/lib/containers/storage/volumes.  Use the intermediate mount
namespace, that is accessible to root in the container, for mounting
the volumes inside the container.

Closes: https://github.com/containers/libpod/issues/2713

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-03-21 21:18:13 +01:00
Daniel J Walsh 9d81be9614
Make sure buildin volumes have the same ownership and permissions as image
When creating a new image volume to be mounted into a container, we need to
make sure the new volume matches the Ownership and permissions of the path
that it will be mounted on.

For example if a volume inside of a containre image is owned by the database
UID, we want the volume to be mounted onto the image to be owned by the
database UID.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-03-15 10:44:44 -04:00
OpenShift Merge Robot 1c45b42e9f
Merge pull request #2585 from giuseppe/build-honor-net
build: honor --net
2019-03-12 12:19:47 -07:00
Matthew Heon 66a72d9283 Ensure that tmpfs mounts do not have symlinks
When mounting a tmpfs, runc attempts to make the directory it
will be mounted at. Unfortunately, Golang's os.MkdirAll deals
very poorly with symlinks being part of the path. I looked into
fixing this in runc, but it's honestly much easier to just ensure
we don't trigger the issue on our end.

Fixes BZ #1686610

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-03-11 14:39:29 -04:00
Giuseppe Scrivano e6139b4824
slirp4netns: add builtin DNS server to resolv.conf
Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-03-11 11:42:01 +01:00
Matthew Heon bb0377eb3d Don't delete another container's resolv and hosts files
The logic of deleting and recreating /etc/hosts and
/etc/resolv.conf only makes sense when we're the one that creates
the files - when we don't, it just removes them, and there's
nothing left to use.

Fixes #2602

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-03-10 12:18:12 -04:00
Daniel J Walsh 2f3875d009
Move secrets package to buildah
Trying to remove circular dependencies between libpod and buildah.

First step to move pkg content from libpod to buildah.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-03-08 16:08:44 -05:00
Peter Hunt 6c8f2072aa Append hosts to dependency container's /etc/hosts file
Before, any container with a netNS dependency simply used its dependency container's hosts file, and didn't abide its configuration (mainly --add-host). Fix this by always appending to the dependency container's hosts file, creating one if necessary.

Signed-off-by: Peter Hunt <pehunt@redhat.com>
2019-03-05 13:15:25 -05:00
Adrian Reber 43fe2bf064
Verify that used OCI runtime supports checkpoint
To be able to use OCI runtimes which do not implement checkpoint/restore
this adds a check to the checkpoint code path and the checkpoint/restore
tests to see if it knows about the checkpoint subcommand. If the used
OCI runtime does not implement checkpoint/restore the tests are skipped
and the actual 'podman container checkpoint' returns an error.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-03-01 08:08:55 +01:00
Adrian Reber 0a8a1deed1
Label CRIU log files correctly
CRIU creates a log file during checkpointing in .../userdata/dump.log.
The problem with this file is, is that CRIU injects a parasite code into
the container processes and this parasite code also writes to the same
log file. At this point a process from the inside of the container is
trying to access the log file on the outside of the container and
SELinux prohibits this. To enable writing to the log file from the
injected parasite code, this commit creates an empty log file and labels
the log file with c.MountLabel(). CRIU uses existing files when writing
it logs so the log file label persists and now, with the correct label,
SELinux no longer blocks access to the log file.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-02-26 11:28:54 +01:00
OpenShift Merge Robot e45c442080
Merge pull request #2358 from rhatdan/namespace
Fix up handling of user defined network namespaces
2019-02-25 21:31:50 +01:00
Daniel J Walsh c83e78277a
In shared networkNS /etc/resolv.conf&/etc/hosts should be shared
We should just bind mount the original containers /etc/resolv.conf and /etchosts
into the new container.  Changes in the resolv.conf and hosts should be seen
by all containers,  This matches Docker behaviour.

In order to make this work the labels on these files need to have a shared
SELinux label.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-02-23 07:52:10 -05:00
Daniel J Walsh b87bdced1f
Fix up handling of user defined network namespaces
If user specifies network namespace and the /etc/netns/XXX/resolv.conf
exists, we should use this rather then /etc/resolv.conf

Also fail cleaner if the user specifies an invalid Network Namespace.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-02-23 05:47:27 -05:00
Sebastian Jug 7141f97270 OpenTracing support added to start, stop, run, create, pull, and ps
Drop context.Context field from cli.Context

Signed-off-by: Sebastian Jug <sejug@redhat.com>
2019-02-18 09:57:08 -05:00
Daniel J Walsh 52df1fa7e0
Fix volume handling in podman
iFix builtin volumes to work with podman volume

Currently builtin volumes are not recored in podman volumes when
they are created automatically. This patch fixes this.

Remove container volumes when requested

Currently the --volume option on podman remove does nothing.
This will implement the changes needed to remove the volumes
if the user requests it.

When removing a volume make sure that no container uses the volume.

Signed-off-by: Daniel J Walsh dwalsh@redhat.com
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2019-02-14 13:21:52 -05:00
OpenShift Merge Robot 5c86efb289
Merge pull request #2138 from giuseppe/rootless-pod-fix
rootless: fix usage of create --pod=new:FOO
2019-01-11 15:42:21 -08:00
Giuseppe Scrivano b3e7be7a0b
spec: add nosuid,noexec,nodev to ro bind mount
runc fails to change the ro mode of a rootless bind mount if the other
flags are not kept.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2019-01-11 10:34:30 +01:00
Matthew Heon 3966d3bf4e Replace tab with spaces in MarshalIndent in libpod
The json-iterator package will panic on attempting to use
MarshalIndent with a non-space indentation. This is sort of silly
but swapping from tabs to spaces is not a big issue for us, so
let's work around the silly panic.

Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-01-10 15:48:09 -05:00
Matthew Heon 167d50a9fa Move all libpod/ JSON references over to jsoniter
Signed-off-by: Matthew Heon <matthew.heon@pm.me>
2019-01-10 15:48:09 -05:00
Valentin Rothberg edb285d176 apparmor: apply default profile at container initialization
Apply the default AppArmor profile at container initialization to cover
all possible code paths (i.e., podman-{start,run}) before executing the
runtime.  This allows moving most of the logic into pkg/apparmor.

Also make the loading and application of the default AppArmor profile
versio-indepenent by checking for the `libpod-default-` prefix and
over-writing the profile in the run-time spec if needed.

The intitial run-time spec of the container differs a bit from the
applied one when having started the container, which results in
displaying a potentially outdated AppArmor profile when inspecting
a container.  To fix that, load the container config from the file
system if present and use it to display the data.

Fixes: #2107
Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
2019-01-09 22:18:11 +01:00
OpenShift Merge Robot 7b9d4f1c92
Merge pull request #2061 from adrianreber/static-ip
Use existing interface to request IP address during restore
2019-01-09 07:41:47 -08:00
Adrian Reber 2553dad766
Use existing interface to request IP address during restore
The initial implementation to request the same IP address for a
container during a restore was based on environment variables
influencing CNI.

With this commit the IP address selection switches to Podman's internal
static IP API.

This commit does a comment change in libpod/container_easyjson.go to
avoid unnecessary re-generation of libpod/container_easyjson.go during
build as this fails in CI. The reason for this is that make sees that
libpod/container_easyjson.go needs to be re-created. The commit,
however, only changes a part of libpod/container.go which is marked as
'ffjson: skip'.

Signed-off-by: Adrian Reber <areber@redhat.com>
2019-01-09 07:34:57 +01:00
W. Trevor King f6a2b6bf2b hooks: Add pre-create hooks for runtime-config manipulation
There's been a lot of discussion over in [1] about how to support the
NVIDIA folks and others who want to be able to create devices
(possibly after having loaded kernel modules) and bind userspace
libraries into the container.  Currently that's happening in the
middle of runc's create-time mount handling before the container
pivots to its new root directory with runc's incorrectly-timed
prestart hook trigger [2].  With this commit, we extend hooks with a
'precreate' stage to allow trusted parties to manipulate the config
JSON before calling the runtime's 'create'.

I'm recycling the existing Hook schema from pkg/hooks for this,
because we'll want Timeout for reliability and When to avoid the
expense of fork/exec when a given hook does not need to make config
changes [3].

[1]: https://github.com/opencontainers/runc/pull/1811
[2]: https://github.com/opencontainers/runc/issues/1710
[3]: https://github.com/containers/libpod/issues/1828#issuecomment-439888059

Signed-off-by: W. Trevor King <wking@tremily.us>
2019-01-08 21:06:17 -08:00
Daniel J Walsh df99522c67
Fixes to handle /dev/shm correctly.
We had two problems with /dev/shm, first, you mount the
container read/only then /dev/shm was mounted read/only.
This is a bug a tmpfs directory should be read/write within
a read-only container.

The second problem is we were ignoring users mounted /dev/shm
from the host.

If user specified

podman run -d -v /dev/shm:/dev/shm ...

We were dropping this mount and still using the internal mount.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-12-24 09:03:53 -05:00
Matthew Heon aa9507054d Containers sharing a netns should share resolv/hosts
When sharing a network namespace, containers should also share
resolv.conf and /etc/hosts in case a container process made
changes to either (for example, if I set up a VPN client in
container A and join container B to its network namespace, I
expect container B to use the DNS servers from A to ensure it can
see everything on the VPN).

Resolves: #1546

Signed-off-by: Matthew Heon <mheon@redhat.com>
2018-12-11 16:56:11 -05:00
Matthew Heon bc57ecec42 Prevent a second lookup of user for image volumes
Instead of forcing another user lookup when mounting image
volumes, just use the information we looked up when we started
generating the spec.

This may resolve #1817

Signed-off-by: Matthew Heon <mheon@redhat.com>
2018-12-11 13:36:50 -05:00
baude 39a036e24d bind mount /etc/resolv.conf|hosts in pods
containers inside pods need to make sure they get /etc/resolv.conf
and /etc/hosts bind mounted when network is expected

Signed-off-by: baude <bbaude@redhat.com>
2018-12-06 13:56:57 -06:00
OpenShift Merge Robot be74acee1c
Merge pull request #1940 from wking/numeric-gid
libpod/container_internal_linux: Allow gids that aren't in the group file
2018-12-05 08:09:58 -08:00
W. Trevor King 650f95cb06 libpod/container_internal_linux: Allow gids that aren't in the group file
When an image config sets config.User [1] to a numeric group (like
1000:1000), but those values do not exist in the container's
/etc/group, libpod is currently breaking:

  $ podman run --rm registry.svc.ci.openshift.org/ci-op-zvml7cd6/pipeline:installer --help
  error creating temporary passwd file for container 228f6e9943d6f18b93c19644e9b619ec4d459a3e0eb31680e064eeedf6473678: unable to get gid 1000 from group file: no matching entries in group file

However, the OCI spec requires converters to copy numeric uid and gid
to the runtime config verbatim [2].

With this commit, I'm frontloading the "is groupspec an integer?"
check and only bothering with lookup.GetGroup when it was not.

I've also removed a few .Mounted checks, which are originally from
00d38cb3 (podman create/run need to load information from the image,
2017-12-18, #110).  We don't need a mounted container filesystem to
translate integers.  And when the lookup code needs to fall back to
the mounted root to translate names, it can handle erroring out
internally (and looking it over, it seems to do that already).

[1]: https://github.com/opencontainers/image-spec/blame/v1.0.1/config.md#L118-L123
[2]: https://github.com/opencontainers/image-spec/blame/v1.0.1/conversion.md#L70

Signed-off-by: W. Trevor King <wking@tremily.us>
2018-12-04 12:00:42 -08:00
W. Trevor King a4b483c848 libpod/container_internal: Deprecate implicit hook directories
Part of the motivation for 800eb863 (Hooks supports two directories,
process default and override, 2018-09-17, #1487) was [1]:

> We only use this for override. The reason this was caught is people
> are trying to get hooks to work with CoreOS. You are not allowed to
> write to /usr/share... on CoreOS, so they wanted podman to also look
> at /etc, where users and third parties can write.

But we'd also been disabling hooks completely for rootless users.  And
even for root users, the override logic was tricky when folks actually
had content in both directories.  For example, if you wanted to
disable a hook from the default directory, you'd have to add a no-op
hook to the override directory.

Also, the previous implementation failed to handle the case where
there hooks defined in the override directory but the default
directory did not exist:

  $ podman version
  Version:       0.11.2-dev
  Go Version:    go1.10.3
  Git Commit:    "6df7409cb5a41c710164c42ed35e33b28f3f7214"
  Built:         Sun Dec  2 21:30:06 2018
  OS/Arch:       linux/amd64
  $ ls -l /etc/containers/oci/hooks.d/test.json
  -rw-r--r--. 1 root root 184 Dec  2 16:27 /etc/containers/oci/hooks.d/test.json
  $ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
  time="2018-12-02T21:31:19-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
  time="2018-12-02T21:31:19-08:00" level=warning msg="failed to load hooks: {}%!(EXTRA *os.PathError=open /usr/share/containers/oci/hooks.d: no such file or directory)"

With this commit:

  $ podman --log-level=debug run --rm docker.io/library/alpine echo 'successful container' 2>&1 | grep -i hook
  time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /usr/share/containers/oci/hooks.d"
  time="2018-12-02T21:33:07-08:00" level=debug msg="reading hooks from /etc/containers/oci/hooks.d"
  time="2018-12-02T21:33:07-08:00" level=debug msg="added hook /etc/containers/oci/hooks.d/test.json"
  time="2018-12-02T21:33:07-08:00" level=debug msg="hook test.json matched; adding to stages [prestart]"
  time="2018-12-02T21:33:07-08:00" level=warning msg="implicit hook directories are deprecated; set --hooks-dir="/etc/containers/oci/hooks.d" explicitly to continue to load hooks from this directory"
  time="2018-12-02T21:33:07-08:00" level=error msg="container create failed: container_linux.go:336: starting container process caused "process_linux.go:399: container init caused \"process_linux.go:382: running prestart hook 0 caused \\\"error running hook: exit status 1, stdout: , stderr: oh, noes!\\\\n\\\"\""

(I'd setup the hook to error out).  You can see that it's silenly
ignoring the ENOENT for /usr/share/containers/oci/hooks.d and
continuing on to load hooks from /etc/containers/oci/hooks.d.

When it loads the hook, it also logs a warning-level message
suggesting that callers explicitly configure their hook directories.
That will help consumers migrate, so we can drop the implicit hook
directories in some future release.  When folks *do* explicitly
configure hook directories (via the newly-public --hooks-dir and
hooks_dir options), we error out if they're missing:

  $ podman --hooks-dir /does/not/exist run --rm docker.io/library/alpine echo 'successful container'
  error setting up OCI Hooks: open /does/not/exist: no such file or directory

I've dropped the trailing "path" from the old, hidden --hooks-dir-path
and hooks_dir_path because I think "dir(ectory)" is already enough
context for "we expect a path argument".  I consider this name change
non-breaking because the old forms were undocumented.

Coming back to rootless users, I've enabled hooks now.  I expect they
were previously disabled because users had no way to avoid
/usr/share/containers/oci/hooks.d which might contain hooks that
required root permissions.  But now rootless users will have to
explicitly configure hook directories, and since their default config
is from ~/.config/containers/libpod.conf, it's a misconfiguration if
it contains hooks_dir entries which point at directories with hooks
that require root access.  We error out so they can fix their
libpod.conf.

[1]: https://github.com/containers/libpod/pull/1487#discussion_r218149355

Signed-off-by: W. Trevor King <wking@tremily.us>
2018-12-03 12:54:30 -08:00
OpenShift Merge Robot f3289fed2e
Merge pull request #1880 from baude/f29fixes
Fix golang formatting issues
2018-11-28 08:18:24 -08:00
OpenShift Merge Robot ade0b30844
Merge pull request #1846 from cgwalters/netns-dns-localhost
Use host's resolv.conf if no network namespace enabled
2018-11-28 07:58:55 -08:00
baude 61d4db4806 Fix golang formatting issues
Whe running unittests on newer golang versions, we observe failures with some
formatting types when no declared correctly.

Signed-off-by: baude <bbaude@redhat.com>
2018-11-28 09:26:24 -06:00
Adrian Reber 0592558289
Use also a struct to pass options to Restore()
This is basically the same change as

 ff47a4c2d5 (Use a struct to pass options to Checkpoint())

just for the Restore() function. It is used to pass multiple restore
options to the API and down to conmon which is used to restore
containers. This is for the upcoming changes to support checkpointing
and restoring containers with '--tcp-established'.

Signed-off-by: Adrian Reber <areber@redhat.com>
2018-11-28 08:00:37 +01:00
Colin Walters 870eed9378 Use host's resolv.conf if no network namespace enabled
My host system runs Fedora Silverblue 29 and I have NetworkManager's
`dns=dnsmasq` setting enabled, so my `/etc/resolv.conf` only has
`127.0.0.1`.

I also run my development podman containers with `--net=host`
for various reasons.

If we have a host network namespace, there's no reason not to just
use the host's nameserver configuration either.

This fixes e.g. accessing content on a VPN, and is also faster
since the container is using cached DNS.

I know this doesn't solve the bigger picture issue of localhost-DNS
conflicting with bridged networking, but that's far more involved,
probably requiring a DNS proxy in the container.  This patch
makes my workflow a lot nicer and was easy to write.

Signed-off-by: Colin Walters <walters@verbum.org>
2018-11-27 15:28:09 -05:00
OpenShift Merge Robot 049defa984
Merge pull request #1850 from vrothberg/mount-propagation
set root propagation based on volume properties
2018-11-27 03:29:17 -08:00
OpenShift Merge Robot 1d3e24239a
Merge pull request #1734 from rhatdan/network
libpod should know if the network is disabled
2018-11-27 03:29:07 -08:00
Valentin Rothberg 0e2042ebd7 set root propagation based on volume properties
Set the root propagation based on the properties of volumes and default
mounts.  To remain compatibility, follow the semantics of Docker.  If a
volume is shared, keep the root propagation shared which works for slave
and private volumes too.  For slave volumes, it can either be shared or
rshared.  Do not change the root propagation for private volumes and
stick with the default.

Fixes: #1834
Signed-off-by: Valentin Rothberg <vrothberg@suse.com>
2018-11-26 13:55:02 +01:00
Adrian Reber b0572d6229
Added option to keep containers running after checkpointing
CRIU supports to leave processes running after checkpointing:

  -R|--leave-running    leave tasks in running state after checkpoint

runc also support to leave containers running after checkpointing:

   --leave-running      leave the process running after checkpointing

With this commit the support to leave a container running after
checkpointing is brought to Podman:

   --leave-running, -R  leave the container running after writing checkpoint to disk

Now it is possible to checkpoint a container at some point in time
without stopping the container. This can be used to rollback the
container to an early state:

$ podman run --tmpfs /tmp --name podman-criu-test -d docker://docker.io/yovfiatbeb/podman-criu-test
$ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample
3
$ podman container checkpoint -R -l
$ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample
4
$ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample
5
$ podman stop -l
$ podman container restore -l
$ curl 10.88.64.253:8080/examples/servlets/servlet/HelloWorldExample
4

So after checkpointing the container kept running and was stopped after
some time. Restoring this container will restore the state right at the
checkpoint.

Signed-off-by: Adrian Reber <areber@redhat.com>
2018-11-20 17:25:44 +01:00
Adrian Reber ff47a4c2d5
Use a struct to pass options to Checkpoint()
For upcoming changes to the Checkpoint() functions this commit switches
checkpoint options from a boolean to a struct, so that additional
options can be passed easily to Checkpoint() without changing the
function parameters all the time.

Signed-off-by: Adrian Reber <areber@redhat.com>
2018-11-20 17:25:44 +01:00
Daniel J Walsh bb6c1cf8d1
libpod should know if the network is disabled
/etc/resolv.conf and /etc/hosts should not be created and mounted when the
network is disabled.

We should not be calling the network setup and cleanup functions when it is
disabled either.

In doing this patch, I found that all of the bind mounts were particular to
Linux along with the generate functions, so I moved them to
container_internal_linux.go

Since we are checking if we are using a network namespace, we need to check
after the network namespaces has been created in the spec.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-11-13 06:33:10 -05:00
Matthew Heon 7e15084d19 Accurately update state if prepare() partially fails
We are seeing some issues where, when part of prepare() fails
(originally noticed due to a bad static IP), the other half does
not successfully clean up, and the state can be left in a bad
place (not knowing about an active SHM mount for example).

Signed-off-by: Matthew Heon <mheon@redhat.com>
2018-11-08 16:51:57 -05:00
OpenShift Merge Robot 1370c311f5
Merge pull request #1771 from baude/prepare
move defer'd function declaration ahead of prepare error return
2018-11-07 10:55:51 -08:00
baude e022efa0f8 move defer'd function declaration ahead of prepare error return
Signed-off-by: baude <bbaude@redhat.com>
2018-11-07 10:44:33 -06:00
Giuseppe Scrivano f813881b81
rootless: mount /sys/fs/cgroup/systemd from the host
systemd requires /sys/fs/cgroup/systemd to be writeable.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2018-11-07 16:10:34 +01:00
Giuseppe Scrivano 11c5b0237b
rootless: don't bind mount /sys/fs/cgroup/systemd in systemd mode
it is not writeable by non-root users so there is no point in having
access to it from a container.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>
2018-11-07 16:10:33 +01:00
baude 1dd7f13dfb get user and group information using securejoin and runc's user library
for the purposes of performance and security, we use securejoin to contstruct
the root fs's path so that symlinks are what they appear to be and no pointing
to something naughty.

then instead of chrooting to parse /etc/passwd|/etc/group, we now use the runc user/group
methods which saves us quite a bit of performance.

Signed-off-by: baude <bbaude@redhat.com>
2018-10-29 08:59:46 -05:00
OpenShift Merge Robot 3efa068528
Merge pull request #1699 from baude/rund
run performance improvements
2018-10-25 05:59:31 -07:00
baude 6246942d37 Increase security and performance when looking up groups
We implement the securejoin method to make sure the paths to /etc/passwd and
/etc/group are not symlinks to something naughty or outside the container
image. And then instead of actually chrooting, we use the runc functions to
get information about a user.  The net result is increased security and
a a performance gain from 41ms to 100us.

Signed-off-by: baude <bbaude@redhat.com>
2018-10-25 06:42:43 -05:00
baude e2aef6341d run prepare in parallel
run prepare() -- which consists of creating a network namespace and
mounting the container image is now run in parallel.   This saves 25-40ms.

Signed-off-by: baude <bbaude@redhat.com>
2018-10-25 06:34:23 -05:00
Adrian Reber 8f6fb79ba8
Use the CRIU version check in checkpoint/restore
The newly introduced CRIU version check is now used to make sure
checkpointing and restoring is only used if the CRIU version is new
enough.

Signed-off-by: Adrian Reber <areber@redhat.com>
2018-10-23 12:52:03 +02:00
Matthew Heon 4a60656dbb Fix CGroup paths used for systemd CGroup mount
We already have functions for retrieving the container's CGroup
path, so use them instead of manually generating a path.

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>
2018-10-17 10:45:58 -04:00
Daniel J Walsh 57a8c2e5e8
Mount proper cgroup for systemd to manage inside of the container.
We are still requiring oci-systemd-hook to be installed in order to run
systemd within a container.  This patch properly mounts

/sys/fs/cgroup/systemd/libpod_parent/libpod-UUID on /sys/fs/cgroup/systemd inside of container.

Since we need the UUID of the container, we needed to move Systemd to be a config option of the
container.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>
2018-10-15 16:19:11 -04:00
Adrian Reber f7c8fd8a3d
Add support to checkpoint/restore containers
runc uses CRIU to support checkpoint and restore of containers. This
brings an initial checkpoint/restore implementation to podman.

None of the additional runc flags are yet supported and container
migration optimization (pre-copy/post-copy) is also left for the future.

The current status is that it is possible to checkpoint and restore a
container. I am testing on RHEL-7.x and as the combination of RHEL-7 and
CRIU has seccomp troubles I have to create the container without
seccomp.

With the following steps I am able to checkpoint and restore a
container:

 # podman run --security-opt="seccomp=unconfined" -d registry.fedoraproject.org/f27/httpd
 # curl -I 10.22.0.78:8080
 HTTP/1.1 403 Forbidden # <-- this is actually a good answer
 # podman container checkpoint <container>
 # curl -I 10.22.0.78:8080
 curl: (7) Failed connect to 10.22.0.78:8080; No route to host
 # podman container restore <container>
 # curl -I 10.22.0.78:8080
 HTTP/1.1 403 Forbidden

I am using CRIU, runc and conmon from git. All required changes for
checkpoint/restore support in podman have been merged in the
corresponding projects.

To have the same IP address in the restored container as before
checkpointing, CNI is told which IP address to use.

If the saved network configuration cannot be found during restore, the
container is restored with a new IP address.

For CRIU to restore established TCP connections the IP address of the
network namespace used for restore needs to be the same. For TCP
connections in the listening state the IP address can change.

During restore only one network interface with one IP address is handled
correctly. Support to restore containers with more advanced network
configuration will be implemented later.

v2:
 * comment typo
 * print debug messages during cleanup of restore files
 * use createContainer() instead of createOCIContainer()
 * introduce helper CheckpointPath()
 * do not try to restore a container that is paused
 * use existing helper functions for cleanup
 * restructure code flow for better readability
 * do not try to restore if checkpoint/inventory.img is missing
 * git add checkpoint.go restore.go

v3:
 * move checkpoint/restore under 'podman container'

v4:
 * incorporated changes from latest reviews

Signed-off-by: Adrian Reber <areber@redhat.com>
2018-10-03 21:41:39 +02:00
Matthew Heon 7ee6bf1573 Disable problematic SELinux code causing runc issues
Signed-off-by: Matthew Heon <matthew.heon@gmail.com>

Closes: #1541
Approved by: baude
2018-09-25 19:32:17 +00:00
Daniel J Walsh 52c1365f32 Add --mount option for `create` & `run` command
Signed-off-by: Kunal Kushwaha <kushwaha_kunal_v7@lab.ntt.co.jp>
Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1524
Approved by: mheon
2018-09-21 21:33:41 +00:00
Daniel J Walsh fbfcc7842e Add new field to libpod to indicate whether or not to use labelling
Also update some missing fields libpod.conf obtions in man pages.

Fix sort order of security options and add a note about disabling
labeling.

When a process requests a new label.  libpod needs to reserve all
labels to make sure that their are no conflicts.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1406
Approved by: mheon
2018-09-20 16:01:29 +00:00
Daniel J Walsh 2cbb8c216a Bind Mounts should be mounted read-only when in read-only mode
We don't want to allow users to write to /etc/resolv.conf or /etc/hosts if in read
only mode.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1510
Approved by: TomSweeneyRedHat
2018-09-20 13:55:35 +00:00
Giuseppe Scrivano 663ee91eec Fix Mount Propagation
Default mount propagation inside of containes should be private

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1305
Approved by: mheon
2018-08-27 13:26:28 +00:00
haircommander 0e6266858a Fixing network ns segfault
As well as small style corrections, update pod_top_test to use CreatePod, and move handling of adding a container to the pod's namespace from container_internal_linux to libpod/option.

Signed-off-by: haircommander <pehunt@redhat.com>

Closes: #1187
Approved by: mheon
2018-08-23 18:16:28 +00:00
haircommander 2a7449362f Change pause container to infra container
Signed-off-by: haircommander <pehunt@redhat.com>

Closes: #1187
Approved by: mheon
2018-08-23 18:16:28 +00:00
haircommander d5e690914d Added option to share kernel namespaces in libpod and podman
A pause container is added to the pod if the user opts in. The default pause image and command can be overridden. Pause containers are ignored in ps unless the -a option is present. Pod inspect and pod ps show shared namespaces and pause container. A pause container can't be removed with podman rm, and a pod can be removed if it only has a pause container.

Signed-off-by: haircommander <pehunt@redhat.com>

Closes: #1187
Approved by: mheon
2018-08-23 18:16:28 +00:00
Giuseppe Scrivano 50afe5b031 podman: fix --uts=host
Do not set any hostname value in the OCI configuration when --uts=host
is used and the user didn't specify any value.  This prevents an error
from the OCI runtime as it cannot set the hostname without a new UTS
namespace.

Differently, the HOSTNAME environment variable is always set.  When
--uts=host is used, HOSTNAME gets the value from the host.

Signed-off-by: Giuseppe Scrivano <gscrivan@redhat.com>

Closes: #1280
Approved by: baude
2018-08-17 08:17:43 +00:00
Daniel J Walsh d20f3a5146 switch projectatomic to containers
Need to get some small changes into libpod to pull back into buildah
to complete buildah transition.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1270
Approved by: mheon
2018-08-16 17:12:36 +00:00
Daniel J Walsh 92e9d7891e We need to sort mounts so that one mount does not over mount another.
Currently we add mounts from images, volumes and internal.
We can accidently over mount an existing mount.  This patch sorts the mounts
to make sure a parent directory is always mounted before its content.

Had to change the default propagation on image volume mounts from shared
to private to stop mount points from leaking out of the container.

Also switched from using some docker/docker/pkg to container/storage/pkg
to remove some dependencies on Docker.

Signed-off-by: Daniel J Walsh <dwalsh@redhat.com>

Closes: #1243
Approved by: mheon
2018-08-10 21:18:19 +00:00
baude 4f699db8da Support multiple networks
This is a refresh of Dan William's PR #974 with a rebase and proper
vendoring of ocicni and containernetworking/cni.  It adds the ability
to define multiple networks as so:

podman run --network=net1,net2,foobar ...

Signed-off-by: baude <bbaude@redhat.com>

Closes: #1082
Approved by: baude
2018-07-12 21:45:47 +00:00
umohnani8 4855998f1c Add --volumes-from flag to podman run and create
podman now supports --volumes-from flag, which allows users
to add all the volumes an existing container has to a new one.

Signed-off-by: umohnani8 <umohnani@redhat.com>

Closes: #931
Approved by: mheon
2018-07-09 19:30:03 +00:00
Matthew Heon eae8007896 Remove per-container CGroup parents
Originally, it seemed like a good idea to place Conmon and the
container it managed under a shared CGroup, so we could manage
the two together. It's become increasingly clear that this is a
potential performance sore point, gains us little practical
benefit in managing Conmon, and adds extra steps to container
cleanup that interfere with Conmon postrun hooks.

Revert back to a shared CGroup for conmon processes under the
CGroup parent. This will retain per-pod conmon CGroups as well if
the pod is set to create a CGroup and act as CGroup parent for
its containers.

Signed-off-by: Matthew Heon <matthew.heon@gmail.com>

Closes: #1051
Approved by: umohnani8
2018-07-06 15:29:38 +00:00
baude cc6f0e85f9 more changes to compile darwin
this should represent the last major changes to get darwin to **compile**.  again,
the purpose here is to get darwin to compile so that we can eventually implement a
ci task that would protect against regressions for darwin compilation.

i have left the manual darwin compilation largely static still and in fact now only
interject (manually) two build tags to assist with the build.  trevor king has great
ideas on how to make this better and i will defer final implementation of those
to him.

Signed-off-by: baude <bbaude@redhat.com>

Closes: #1047
Approved by: rhatdan
2018-07-05 16:05:12 +00:00
baude b96be3af1b changes to allow for darwin compilation
Signed-off-by: baude <bbaude@redhat.com>

Closes: #1015
Approved by: baude
2018-06-29 20:44:09 +00:00