Skip to content

Commit b634390

Browse files
committed
ccon: Add '--socket PATH' to support a create/start split
Along the lines of the create/start split we've been discussing for the OCI [1,2]. Pull some common functionality into a libccon, although I don't intend to make that a more than an internal helper. Post-error cleanup in ccon-cli is pretty slim, since the process is just about to die anyway. I'll probably go back through and add proper cleanup later. serve_socket gets too deeply nested for my taste, but it's not quite to the point where I'd pull out the request handling into a handle_start_request helper or some such. Mostly because I'd have to either setup a new buf/iov/msg in the helper's stack or pass that all through from serve_socket ;). A few notes on the tests: I don't have a stand-alone 'wait' on my system (it's built into most shells [3]), but I've added an explicit check for it because POSIX doesn't require it to be built in. The waiting in the create/start tests is a bit awkward, but here's the reasoning for the various steps: * Put the socket in a 'sock' subdirectory so we don't have to mess with inotifywait's --exclude (when what we really want is an --include). In most cases, the socket would be the first thing created in the test directory, but the process.host test will create a pivot-root.* before creating the socket. * Clear a 'wait' file before launching the inotifywait/start subshell and append to it from that subshell so grep has something to look at (even if it racily starts looking before the subshell processes the inotifywait line). * Block on a busy-wait grep until inotifywait sets up its watcher. This ensures we don't call ccon and create the socket before the watcher is looking. The zero-second sleep while we wait for inotifywait to setup its watcher is busy, but POSIX doesn't require 'sleep' to support non-integer times [4]. All of these issues could be abstracted out into an 'event' command [5], but they're fine for a proof-of-concept create/start split. [1]: https://groups.google.com/a/opencontainers.org/d/msg/dev/qWHoKs8Fsrk/k55FQrBzBgAJ Subject: Re: Splitting Start into create() and run() Date: Thu, 24 Mar 2016 15:04:14 -0700 Message-ID: <[email protected]> [2]: opencontainers/runtime-spec#384 Subject: Split create and start [3]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap01.html#tag_17_06 [4]: http://pubs.opengroup.org/onlinepubs/9699919799/utilities/sleep.html [5]: opencontainers/runtime-spec#508 Subject: runtime: Add an 'event' operation for subscribing to pushes
1 parent 1077e0d commit b634390

File tree

12 files changed

+1166
-293
lines changed

12 files changed

+1166
-293
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
ccon
2+
ccon-cli
23
*.o

Makefile

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@ LDLIBS := $(shell pkg-config --libs-only-l jansson libcap-ng)
66
.PHONY: all clean fmt
77
.PRECIOUS: %.o
88

9-
all: ccon
9+
all: ccon ccon-cli
1010

1111
%.o: %.c
1212
$(CC) $(CFLAGS) -c -o "$@" "$<"
1313

14-
ccon: %: %.o
15-
$(CC) $(LDFLAGS) -o "$@" "$<" $(LDLIBS)
14+
ccon ccon-cli: %: %.o libccon.o
15+
$(CC) $(LDFLAGS) -o "$@" $^ $(LDLIBS)
1616

1717
clean:
18-
rm -f *.o ccon
18+
rm -f *.o ccon ccon-cli
1919

2020
fmt:
21-
indent --ignore-profile --linux-style *.c
21+
indent --ignore-profile --linux-style *.h *.c

README.md

Lines changed: 85 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ less opinionated than [LXC][lxc.container.conf.5]).
1111
## Table of contents
1212

1313
* [Lifecycle](#lifecycle)
14+
* [Socket communication](#socket-communication)
15+
* [Getting the container process's
16+
PID](#getting-the-container-processs-pid)
17+
* [Start request](#start-request)
1418
* [Configuration](#configuration)
1519
* [Version](#version)
1620
* [Namespaces](#namespaces)
@@ -59,8 +63,11 @@ synchronize the container setup. Here's an outline of the lifecycle:
5963
| | mounts filesystems |
6064
| | ← sends namespaces-complete |
6165
| runs pre-start hooks | blocks on exec-message |
62-
| sends exec-message → | |
63-
| | opens the local ptmx |
66+
| binds to socket path | |
67+
| sends connection socket → | |
68+
| blocks on exec-process message | listens for process JSON |
69+
| | ← sends exec-process message |
70+
| removes socket path | opens the local ptmx |
6471
| | ← sends pseudoterminal master |
6572
| | bind mounts `/dev/console` |
6673
| | ← sends pseudoterminal slave |
@@ -86,6 +93,77 @@ use [`nsenter`][nsenter.1] or a wrapping ccon invocation to join those
8693
namespaces before the main ccon invocation creates the new mount
8794
namespace.
8895

96+
## Socket communication
97+
98+
With `--socket=PATH`, ccon will bind a [`SOCK_SEQPACKET` Unix
99+
socket][unix.7] to `PATH`. This path is created after namespace-setup
100+
completes, so users can use its presence as a trigger for further
101+
configuration (e.g. network setup) before [starting](#start-request)
102+
the [user-specified code](#process). The path is removed after a
103+
[start request](#start-request) is received or after the container
104+
process exits, whichever comes first.
105+
106+
The [`ccon-cli`](ccon-cli.c) program distributed with this repository
107+
is one client for the ccon socket.
108+
109+
### Getting the container process's PID
110+
111+
An [`SO_PEERCRED`][socket.7] request will return the container
112+
process's PID [in the receiving process's PID
113+
namespace][pid_namespaces.7]. The client can use this to look up the
114+
container process in their local [`/proc`][proc.5]. This request may
115+
be performed as many times as you like.
116+
117+
### Start request
118+
119+
The request is a single [`struct iovec`][recv.2] containing either a
120+
leading null byte or process JSON. Sending a single null-byte message
121+
will trigger the [**`process`**](#process) field present in the
122+
original configuration, while non-empty strings will completely
123+
override that field.
124+
125+
The response is a single [`struct iovec`][recv.2] containing either a
126+
single null-byte message (for success) or an error message encoded in
127+
[ASCII][ascii.7] ([RFC 1345][rfc1345.s5]). In this context, “success”
128+
means “successfully received the start request”, because the container
129+
process sends the response before actually executing the
130+
[user-specified code](#process).
131+
132+
If you set [**`host`**](#host) in your process JSON, `ccon-cli` will
133+
open the referenced path and pass the open file descriptor to the
134+
container over the Unix socket.
135+
136+
### Example
137+
138+
In one shell, launch ccon and have it listen on a socket at
139+
`/tmp/ccon-sock`:
140+
141+
```
142+
$ ccon --socket /tmp/ccon-sock
143+
```
144+
145+
In a second shell, get the container process's PID, but don't trigger
146+
the user-specified code:
147+
148+
```
149+
$ PID=$(ccon-cli --socket /tmp/ccon-sock --pid)
150+
$ echo "${PID}"
151+
2186
152+
```
153+
154+
You can then perform additional configuration using that PID:
155+
156+
```
157+
$ ip link set ccon-ex-veth1 netns "${PID}"
158+
```
159+
160+
And when you're finished setting up the environment, you can trigger
161+
the [user-specified code](#process):
162+
163+
```
164+
$ ccon-cli --socket /tmp/ccon-sock --config-string '{"args": ["busybox", "sh"]}'
165+
```
166+
89167
## Configuration
90168

91169
Ccon is similar to an [Open Container Iniative Runtime
@@ -858,6 +936,7 @@ be distributed under the GPLv3+.
858936
[setgid.2]: http://man7.org/linux/man-pages/man2/setgid.2.html
859937
[setuid.2]: http://man7.org/linux/man-pages/man2/setuid.2.html
860938
[syscall.2]: http://man7.org/linux/man-pages/man2/syscall.2.html
939+
[recv.2]: http://man7.org/linux/man-pages/man2/recv.2.html
861940
[environ.3p]: https://www.kernel.org/pub/linux/docs/man-pages/man-pages-posix/
862941
[exec.3]: http://man7.org/linux/man-pages/man3/exec.3.html
863942
[getcwd.3]: http://man7.org/linux/man-pages/man3/getcwd.3.html
@@ -868,11 +947,14 @@ be distributed under the GPLv3+.
868947
[pts.4]: http://man7.org/linux/man-pages/man4/pty.4.html
869948
[filesystems.5]: http://man7.org/linux/man-pages/man5/filesystems.5.html
870949
[lxc.container.conf.5]: https://linuxcontainers.org/lxc/manpages/man5/lxc.container.conf.5.html
950+
[proc.5]: https://linuxcontainers.org/lxc/manpages/man5/proc.5.html
951+
[ascii.7]: http://man7.org/linux/man-pages/man7/ascii.7.html
871952
[capabilities.7]: http://man7.org/linux/man-pages/man7/capabilities.7.html
872953
[namespaces.7]: http://man7.org/linux/man-pages/man7/namespaces.7.html
873954
[pid_namespaces.7]: http://man7.org/linux/man-pages/man7/pid_namespaces.7.html
874955
[pty.7]: http://man7.org/linux/man-pages/man7/pty.7.html
875956
[signal.7]: http://man7.org/linux/man-pages/man7/signal.7.html
957+
[socket.7]: http://man7.org/linux/man-pages/man7/socket.7.html
876958
[unix.7]: http://man7.org/linux/man-pages/man7/unix.7.html
877959
[user_namespaces.7]: http://man7.org/linux/man-pages/man7/user_namespaces.7.html
878960
[mount.8]: http://man7.org/linux/man-pages/man8/pty.8.html
@@ -881,4 +963,5 @@ be distributed under the GPLv3+.
881963
[cgroups]: https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt
882964
[cgroups-unified]: https://www.kernel.org/doc/Documentation/cgroup-v2.txt
883965
[devpts]: https://www.kernel.org/doc/Documentation/filesystems/devpts.txt
966+
[rfc1345.s5]: https://tools.ietf.org/html/rfc1345#section-5
884967
[sd_listen_fds]: http://www.freedesktop.org/software/systemd/man/sd_listen_fds.html

0 commit comments

Comments
 (0)