"clean up" is a verb, and "cleanup" is a noun. There are several
examples of the incorrect usage of "cleanup" as a verb in this
repository, including one in the public API (`cleanupOrphanedBlobs`).
For this public method, I've added a deprecation notice to the name with
the incorrect usage.
Fixes#79
This adds support for single file (virtiofs based) mounts to the two
main container types. This is transparent, and doesn't need to be setup
by a user, so there is no visible API change. Virtiofs does not support
single file mounts today, and it would be less than ideal from a
security standpoint to just expose the parent directory of the file to
the vm and then bind mount in the file, so we chose the following:
1. Create a temp directory the container types will manage.
2. Hardlink in the file we want.
3. Share that tempdir into the vm.
4. Finally bind mount in the file into the container.
The main goal I wanted for this is to leave the logic out of the
`VirtualMachineInstance`. I really want this to just be a little dance
the container types do, and leave the vm out of it. Because of that,
most of the logic is shoved in a new `FileMountContext` type that does
the dirty tricks of rewriting what the user asked for to be a bind mount
from a temporary holding spot we'll use in the guest for these temp
directories.
One of the downsides to this is today the tempdirs are solely on the
main volume, so cross volume will need to copy the file to the tempdir,
so writes won't get written back.
Co-authored-by: Dean Coulstock <d_coulstock@apple.com>
Co-authored-by: Jaewon Hur <hurjaewon@snu.ac.kr>
When we set a gateway outside a subnet in Linux, this fails with:
```
ip-route-add-default: netlink response indicates error, rc = -101
```
To resolve the error, we should first add a route to the gateway outside
the subnet, which this PR does.
The guest agent isn't free, and today we were sizing the VMs memory
allotment and the containers cgroup to the same value. This change gives
some overhead memory to the VM (50MB for now) for the guest agent.
It's possible a user doesn't want the full stats list, and only wants
cpu/mem etc. This plumbs through the ability to filter to only what is
requested. This, while we're already here, adds in memory.event output
to the stats list. For that specifically, I think eventually we may want
a streaming variant of this so you can get alerted of changes in the
file immediately instead of polling/one off reads, but this is useful
for now.
Add a streaming rpc to copy single files in and out. This can easily be
extended to support copying directories, but we need the guest agent to
be able to tar/untar, and we'll need to figure out what that model is.
Taking in a filehandle gives the user quite a bit more freedom on how to
handle boot log output. They can set up a kqueue watch on it and
redirect output somewhere else etc etc. The implementation for this has
us take in a new BootLog type that has two options:
1. .file, which is analogous to what we had prior. Just provide a URL
and a true by default append field.
2. .fileHandle which is the new addition. Can pass any fd that is
writable, and the VMM should write serial console output to it.
This change is aimed at making forgetting to call .delete() on a
LinuxProcess less destructive than it can be. Because Virt.framework
invalidates any vsock fds it vended if the vm is stopped, trying to
perform some operations on the grpc client through any of the process
methods could trigger an ebadf, which NIO asserts on. This keeps a
reference to the execs and deletes all of them for you once the
container dies. I still think leaving .delete a public method is useful
as otherwise the stdio fds are left open, but cleanup should occur all
in one place now if you don't care about this.
This additionally:
1. Fixes two of our tests that forgot to delete() an exec.
2. Adds two new tests to verify that process.delete() is now idempotent,
and we don't need to call delete().
This was a funny oversight. We have two port spaces, one for listening
sockets on the host, and one for vsock proxies in the guest, but only
the host "allocator" was being used. This didn't really matter as the
ports in the guest would still be unique, but would still be good to
fix.
- Current implementation shuts down everything as soon as EOF is
detected on DispatchSourceRead for the relay. This is problematic for,
say an HTTP request where the client makes a request, and calls
`shutdown(fd, SHUT_WR)` to close the send side, but it expects to be
able to keep calling `recv()` to get the response.
- Changed cancel handlers so that the one that sees that both sources
have been cancelled then closes both the UDS and vsock fds.
- Updated vminitd VsockProxy to also do `shutdown(fd, SHUT_WR)` for read
hangup or EOF, and only close the underlying fds and unwire pollers on
full hangup, broken pipe, error, or when both sides half-close.
Closes#319
Introduces a new type capable of running > 1 container in the guest. The
API mostly follows LinuxContainer, and each individual container can be
addressed via any of the methods that require you to pass the
containerID as the first param. Today there's no support for namespace
sharing, but that shouldn't be terrible to support.
Closes#227
Previously, the bootlog was supplied once in the constructor to
VZVirtualMachineManager which meant that if you used this same manager
for multiple ctrs that all logs would end up going to the same file,
which becomes quite cumbersome to follow..
This change moves bootlog to be a container configuration param and also
moves it to be a VMConfiguration param, so it can be threaded through
from LinuxContainer -> vmm.create() and be truly container unique now.
The largest driver for this was the integration tests which today every
single test spits out logs to a singular file, making guest
investigations tricky to actually look into.
Result after:
```
➜ containerization git:(bootlog-per-ctr) ✗ ls -alh bin/bootlogs
total 1520
drwxr-xr-x@ 24 dcantah staff 768B Oct 22 17:34 .
drwxr-xr-x@ 8 dcantah staff 256B Oct 22 17:34 ..
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-cat-mount.log
-rw-------@ 1 dcantah staff 22K Oct 22 17:34 test-cgroup-limits.log
-rw-------@ 1 dcantah staff 249K Oct 22 17:34 test-concurrent-processes-output-stress.log
-rw-------@ 1 dcantah staff 167K Oct 22 17:34 test-concurrent-processes.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-container-devconsole.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-container-hostname.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-container-hosts-file.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-container-manager.log
-rw-------@ 1 dcantah staff 22K Oct 22 17:34 test-container-reuse.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-container-statistics.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-container-stdin.log
-rw-------@ 1 dcantah staff 0B Oct 22 17:34 test-nested-virt.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-pause-resume-io.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-pause-resume-wait.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-pause-resume.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-process-custom-home-envvar.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-process-echo-hi.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-process-false.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-process-home-envvar.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-process-true.log
-rw-------@ 1 dcantah staff 11K Oct 22 17:34 test-process-tty-envvar.log
-rw-------@ 1 dcantah staff 38K Oct 22 17:34 test-process-user.log
```
Today this protocols create method is just odd. Our only implementation
of it immediately casts to LinuxContainer, failing if it cannot do so. I
think what might make more sense is to pass in a configuration itself
with core parameters that we expect every vmm to be able to support, and
then in a specific implementation they can continue to cast this type to
a specific one to possibly extract some extra configuration values
(rosetta for VZ for example).
This rework will also make it simpler to support a Pod type, as the vm
setup is identical and simple.
As a first step to making a pod type, move the nested process
configuration out of LinuxContainer.Configuration.Process and into a
standalone LinuxProcessConfiguration type.
The `vmm.create` call is already made within an async function. This PR
updates the protocol to allow other vmm implementations more flexibility
in `create`.
Signed-off-by: Kathryn Baldauf <k_baldauf@apple.com>
This change moves LinuxContainer to use the new AsyncMutex type. This allows us to keep using our old state machine model, but lock around the entirety of operations. This also allows us to axe quite a few states that were intermediary states only there to protect against multiple threads calling (even if it was unlikely..) the same method at the same time (.creating, .starting, .stopping etc.).
The rationale is: Mutex is somewhat tricky to use as you can't (for good reason) do any async work inside the closure. This makes some of our work difficult as every single interaction with the guest is via an rpc, which is all async. There really isn't a worry about contention, because most container methods will only ever be invoked once (create, start, stop) so a big heavy lock isn't much of a deterrent.
Fixes#320
Today we don't actually setup any cgroup limits, as because there's a
1-1 mapping from container<->vm we can just use the VMs resources as the
limit (can't use more than 1GB if that's all the guest sees :) ).
However, if we ever supported > 1 container in the guest it'd be
necessary to actually setup the cg limits. This change just sets a
memory limit and cpu toggles to match whatever was specific for the
container.
Closes#138
This rounds up cgroup and network stats (via netlink) and exposes them
via an agent rpc and on LinuxContainer. While this is not an entirely
accurate view into the full resources being used by the container given
the virtualized nature (doesn't account for vcpu, device etc overhead)
it should give an accurate overview of the workload resource usage in
the guest.
This change besides the stated goal also removes the interfaceStatistics
rpc and just moves these network stats into the new containerStatistics
one. Related to that, it also renames the InterfaceStatistics struct to
NetworkStatistics and moves this into ContainerStatistics as a nested
struct.
Have wait return a struct containing the exit code and the time at which
the process actually exited. This is useful so higher level tools (like
container) don't need to craft a date themselves, and it will be more
accurate as it's taken in the guest directly after the process exits.
We currently weren't doing any cgroup setup whatsoever. For the most
part this doesn't matter too much, however certain images that may fool
around with cgroups don't like this :). Lets do the bare minimum these
expect which is to at least have the process running in a nested cg and
not apart of the root cg.
After the container is stopped it's a bit odd how we don't allow the
object to be restarted. If someone wanted to continuously rerun the same
container they'd need to make a new object every time even though all
guest state is blown away on stop() so it's a clean slate.
This change makes it so that you can create+start again after stop
(although create stands out like a sore thumb now as stop -> create is
just strange).
This is a fairly large reworking, but it gets rid of something that has
plagued this since release which is the properties needing to be locked
to be Sendable compliant. This was somewhat of a copout because we
mostly know there's not a great deal of ways to have misused the setup
today, but alas we'd need to either mark the type as `@unchecked` or
just find a different route for setting the configuration. This change:
Exposes the underlying Configuration type that today only housed things
that aren't on the OCI spec. I'd love to just expose the OCI spec, but
we don't (and possibly never will) support everything on the spec, so
exposing it to be freely modified would be a bit odd. Now everything
related to the container is configured on this type, and the same goes
for execs.
Closes#206
Much like we have support for supplying DNS configurations and writing
out /etc/resolv.conf, this adds a way to write out /etc/hosts for a
given container.
- The `@SendableProperty` macro now checks for supported types to
prevent a misuse with unsupported types like structs, dictionaries, and
arrays
- The new `@SendablePropertyUnchecked` can be used with classes and
enums
This allows the user the ability to raise an EOF for the containers
stdin. Today there's no way to close stdin so something as simple as
"cat" and relying on EOF to move the process forward doesn't work
Here we implement the mechanism for ensuring that `container` doesn't
set up two default routes on containers that connect to multiple
networks. We'll implement the policy in apple/container#243.
Make sure we always set TERM for containers that ask for a tty. Right
now this handling was spread around in a bunch of spots, but I'd wager
setting it for the client on the host via LinuxContainer/Process is more
sane and already what we do for a lot of the other fields.
## Changes
### README.md
- Fixed grammatical error: "when a process is ran" → "when a process is
run"
- Fixed plural form: "for instruction on" → "for instructions on"
### kernel/README.md
- Fixed numbering sequence: "4. Run `make`" → "3. Run `make`" in build
instructions
### Sources/Containerization/LinuxContainer.swift
- Fixed grammatical error in comment: "The container has ran" → "The
container has run"