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.
Adds support for grabbing stats for an iface. This will be surfaced in a
coming change to get container level statistics from the guest, where
one field will be network stats.
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.
This refactors the rootfs command to produce an image and have the
ability to create an ext4 formatted block of the init filesystem
directly from the command.
closes#220
Signed-off-by: crosbymichael <michael_crosby@apple.com>
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.
The `allocations` property in the nested `Allocator` structure wasn't
updated. This PR resolves the problem by using mutating methods and
keeping the original types as structs.
This change adds in a new rpc that we probably should swap to for the
underlying implementation of a couple rpcs we currently have. This new
rpc simply writes to an existing or new file some data. This is useful
for guest (and container) setup for things like /etc/hosts,
/etc/resolv.conf, writing to one-off cgroup files and so on.
Currently I've just implemented subtree_control toggling for the root cg
in standardSetup with this new change, but in the future I'd like to
swap the implementations of our /etc/hosts and /etc/resolv.conf logic
with this.
This PR replaces public computed properties with setters in the
`NATNetworkInterface` class with constants to avoid using locks in the
setters. A new instance of `NATNetworkInterface` should be created to
change these values.
This reverts commit 5f7dcd2a16. Rosetta is
setup at /run because the guest rootfs is ro, and unfortunately this
happens prior to LinuxContainer getting to mount any of this. I'm not
super happy about this, but we can figure something out later.
Additionally this adds a rosetta flag to cctl so we can quickly
spotcheck things like this again.
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).
A ContainerManager is a type that handles more of the required resource
needed to create and run a container.
---------
Signed-off-by: crosbymichael <michael_crosby@apple.com>
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.
In general I believe it's clever to synthesize an index for
single-platform image manifest, but we still need a way to distinguish
it. Add a dedicated annotation is the slightest change I've come up
with, and it's also OCI compliant. With this change come in, we can work
around https://github.com/apple/container/issues/212 and imitate the
behavior of other runtime with `container`.
Note that since `cctl` is meant to be a dedicated tool for inspecting
the Containerization framework itself, I didn't apply the indirection
for it, and it will be as-is with the genuine storage.
- 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
While this only supports AS, xcode's default will build all arches, so
this presents a bit nicer default for Archiving an xcode application
that utilizes containerization.
Fixes#179
Signed-off-by: crosbymichael <michael_crosby@apple.com>
Creates a new Unpacker protocol that defines a single method
```
func unpack(_ image: Image, for platform: Platform, at path: URL, progress: ProgressHandler?) async throws -> Mount
```
This change also removes the `unpack(...)` method from the Image type.
Before
```
let mount = try await image.unpack(for: platform, at: path)
```
After
```
let unpacker = EXT4Unpacker(blockSizeInBytes: 2.gib())
let mount = try await unpacker.unpack(image, for: platform, at: path)
```
---------
Signed-off-by: Aditya Ramani <a_ramani@apple.com>
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.
Because we were installing rosetta directly in the constructor for
VZVirtualMachineInstance, and we'd prefer to not have the constructor
async as it pollutes so much more, we had devised this gnarly callback
approach for the install that is a bit of an eyesore. This changes focus
is on moving the install flow to a method that is already async so we
can piggyback off of it, and removing the install logic from the config
-> VZConfig conversion. Now the install will occur during start() if
rosetta is not installed.
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"