245 Commits
Author SHA1 Message Date
Lai Jiangshan f359cb9468 Merge pull request #150 from laijs/v0.6.2
bump version to 0.6.2
2016-08-29 17:27:01 +08:00
Lai Jiangshan 3de74e927c bump version to 0.6.2
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-08-29 17:18:06 +08:00
Lai Jiangshan 7b54d5c9da Merge pull request #149 from gao-feng/limit
setup Limit by default
2016-08-29 16:55:35 +08:00
Gao feng 1e4711d898 setup file-max by default
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-08-29 16:06:14 +08:00
Gao feng cb71f43ed1 blow up rlimit of process
NOFILE: 1000000:1000000
NPROC: 30604:30604
SIGPENGING: 30604:30604

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-08-29 16:05:15 +08:00
Gao feng c72276b004 Merge pull request #146 from bergwolf/mkdir-for-file-volume-only
do not create _data dir without checking first
2016-08-14 14:49:17 +08:00
Peng Tao 5735f9f674 free scandir list in non file volumes case
Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-08-14 13:54:06 +08:00
Peng Tao de0c2c97e4 do not create _data dir without checking first
container_populate_volume() checks _data existance to determine if it
should populate old data. We only need to create new _data with 0777
mode if there is no existing one. That includes two cases:
1. before populating old data in container_populate_volume()
2. mount an empty volume for the fist time

For file volume case, we need to chmod it instead, to make sure any user
is able to read/write the file.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-08-14 11:00:45 +08:00
Lai Jiangshan 8a86dd1f51 Merge pull request #144 from bergwolf/file-vol
fix up file volume binding handling
2016-08-10 22:41:48 +08:00
Peng Tao 5ba9b2550d handle directory destination for a file volume binding
If the destination directoroy does not exist in the base image,
create it as a file instead, following docker's practice.

[hyperpublic@hyperhq]$docker run -t -i -v /home/bergwolf/bin/procmuttmail:/vol/data/ busybox
/ # ls -l /vol/data
-rwxr-xr-x    1 1000     1000            28 Apr 17 05:38 /vol/data
/ #

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-08-10 18:03:52 +08:00
Peng Tao da986b4a3a create file volume's parent directory when necessary
Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-08-10 18:02:05 +08:00
Gao feng 2f4626dde2 Merge pull request #142 from laijs/enter-sandbox
enter the sandbox when hyper_setup_container_rootfs()
2016-08-02 22:30:03 +08:00
Lai Jiangshan bf61d6306e enter the sandbox when hyper_setup_container_rootfs()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-08-02 11:15:45 +08:00
Lai Jiangshan 74f6930073 add hyper_enter_sandbox()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-08-02 11:15:45 +08:00
Lai Jiangshan 0c05c999e3 remove tty from struct hyper_win_size
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-08-02 11:15:45 +08:00
Lai Jiangshan 97099eb46e declare functions to static
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-08-02 11:15:45 +08:00
Lai Jiangshan b28a02fa0d Merge pull request #140 from gao-feng/event2
[RFC]  handle ttyfd out event priorly when write buffer is full
2016-08-01 09:39:50 +08:00
Gao feng 9a6738d84d handle ttyfd out event priorly when write buffer is full
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-07-29 15:57:45 +08:00
Lai Jiangshan d3cfa23dde Merge pull request #139 from gao-feng/revert
Revert "move mount /proc to hyper_container_final_init()"
2016-07-21 10:07:15 +08:00
Gao feng 9bfb3be414 Revert "move mount /proc to hyper_container_final_init()"
running in child process, fail to setup finalinit

This reverts commit b0a601793e.
2016-07-21 10:02:58 +08:00
Gao feng ae2d491c20 Merge pull request #138 from laijs/mount-proc
Mount proc when first exec
2016-07-20 17:15:57 +08:00
Lai Jiangshan b0a601793e move mount /proc to hyper_container_final_init()
exec can be run earlier than start container.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-20 16:58:44 +08:00
Lai Jiangshan 19f1dc012e refactor struct hyper_container
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-20 15:28:55 +08:00
Lai Jiangshan 87b1a5c29a add missing pod->remains++
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-20 12:24:48 +08:00
Lai Jiangshan 4a63bceb67 Merge pull request #137 from bergwolf/volume_mode
create volume _data dir with 0777 mode
2016-07-19 09:13:15 +08:00
Peng Tao b2f6b89ea6 move hyper_create_file to util.h
Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-07-18 20:55:52 +08:00
Peng Tao db4f364510 create volume _data dir with 0777 mode
So that any user is able to write to the new volume.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-07-18 20:55:32 +08:00
Gao feng 2ccea842bd Merge pull request #136 from bergwolf/hyper_cp
hyper_copy_dir should use hyper_cmd
2016-07-18 13:24:44 +08:00
Peng Tao 3197bcad45 hyper_copy_dir should use hyper_cmd
Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-07-16 16:01:24 +08:00
Lai Jiangshan 3bed96c176 Merge pull request #133 from gao-feng/env
env: setup envs of container for exec
2016-07-15 16:40:43 +08:00
Gao feng eecb4c5612 env: setup envs of container for exec
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-07-15 15:07:27 +08:00
Gao feng c015887bb6 Merge pull request #132 from gao-feng/bug
cleanup & fix zombie process bug
2016-07-14 22:55:38 +08:00
Gao feng 2169309145 exec: restore sigmask of child process
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-07-14 19:37:21 +08:00
Gao feng c5d25b6f5f event: rename de to he
dvm_event has been removed long long ago.

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-07-14 19:26:37 +08:00
Gao feng da6b36411a remove useless var global_exec
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-07-14 19:22:09 +08:00
Lai Jiangshan 06d10f2844 Merge pull request #130 from gao-feng/proc
mount proc filesystem of container in enter_container
2016-07-07 21:08:46 +08:00
Gao feng 70d35640b9 mount proc filesystem of container in enter_container
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-07-07 18:50:47 +08:00
Gao feng 1f501c5417 Merge pull request #129 from bergwolf/shutdown_on_error
send ERROR to runv when shutting down upon errors
2016-07-07 09:14:46 +08:00
Gao feng 1c21bb2e6f Merge pull request #128 from laijs/open-ns
wait until mount namespace fd is opened
2016-07-07 09:14:07 +08:00
Lai Jiangshan b6c6e1f991 wait until mount namespace fd is opened
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-06 19:28:55 +08:00
Peng Tao 98059369b8 send ERROR to runv when shutting down upon errors
Otherwise ACK might let runv think its command succeeds.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-07-06 19:19:06 +08:00
Gao feng 03187117e1 Merge pull request #127 from laijs/container-and-exec-operations
split container operation to hyper_setup_container() and hyper_run_process()
2016-07-06 19:04:23 +08:00
Lai Jiangshan 54aed5efc5 split container operation to hyper_setup_container() and hyper_run_process()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-06 17:15:42 +08:00
Lai Jiangshan 98b8211ddc move hyper_start_containers() to hyper_start_pod()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-06 15:55:07 +08:00
Lai Jiangshan cd9a8f4306 set early env for exec
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-06 14:05:46 +08:00
Lai Jiangshan bb550c2444 do not apply the container's env on exec
let the hyperd do it. (merge the envs)

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-06 14:05:33 +08:00
Lai Jiangshan 00308d00b5 split hyper_exec_cmd()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-06 11:39:27 +08:00
Gao feng e255de660d Merge pull request #126 from laijs/exec-fork
Exec:  use fork() instead of the fragile clone(CLONE_VM|CLONE_FILES)
2016-07-05 12:58:25 +08:00
Lai Jiangshan ca004ec273 use fork() instead of fragile clone(CLONE_VM|CLONE_FILES)
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-05 10:49:08 +08:00
Lai Jiangshan 52aca5a860 Merge pull request #125 from laijs/rootfs
use /tmp/hyperstart-rootfs as temporary rootfs
2016-07-05 09:50:12 +08:00
Lai Jiangshan 5fcac6f0bb move the call of hyper_watch_exec_pty() to parent(init) process
so we don't need to touch the parent's memory nor file table.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-04 22:46:50 +08:00
Lai Jiangshan 216bce6fe0 don't wait hyper_do_exec_cmd() via waitpid()
wait it via hyper_get_type()

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-04 22:36:52 +08:00
Lai Jiangshan e8381942d4 send pid back to parent rather than touch the parent's memory directly
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-04 22:12:21 +08:00
Lai Jiangshan 51dc391bc0 all exec should have container id
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-04 21:58:05 +08:00
Lai Jiangshan 73a9c3e8e9 use /tmp/hyperstart-rootfs as temporary rootfs
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-07-04 20:56:00 +08:00
Gao feng 505ad4ddb0 Merge pull request #121 from YaoZengzeng/delete-container
Support for removing container
2016-07-01 11:23:44 +08:00
YaoZengzeng 20158b9033 Support for removing container
Signed-off-by: Yao Zengzeng <yaozengzeng@foxmail.com>
2016-06-30 19:59:18 -07:00
Gao feng 1e6dffd36f Merge pull request #123 from laijs/introduce-parson
Introduce parson
2016-06-30 15:30:48 +08:00
Lai Jiangshan d919414192 use parson to parse kill command
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-30 12:09:15 +08:00
Lai Jiangshan b15d771a56 add const to container id in hyper_find_container()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-30 12:05:01 +08:00
Lai Jiangshan b99768db28 add parson(github.com/kgabis/parson)
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-30 11:17:44 +08:00
Lai Jiangshan 1a612982e8 Merge pull request #122 from gao-feng/cleanup
remove useless field in hyper_pod
2016-06-29 17:13:48 +08:00
Gao feng 3f034fec04 remove useless field in hyper_pod
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-06-29 14:25:41 +08:00
Lai Jiangshan 831113b7d0 Merge pull request #118 from bergwolf/kvm-nested
enable kvm and devmem in guest kernel
2016-06-27 12:18:56 +08:00
Lai Jiangshan 64aeb1ceca Merge pull request #120 from bergwolf/file-vol
support file destination volume
2016-06-27 12:10:59 +08:00
Peng Tao 11c7507eed support file destination volume
If a volume source contains only one file named ".hyper_file_volume_data_do_not_create_on_your_own",
bind mount it as a file to the specified mountpoint inside container's namespace, rather than
mounting its parent directory.

The special name .hyper_file_volume_data_do_not_create_on_your_own is
agreed upon with client which would save a file as this name if it wants
to bind mount a single file rather than a directory.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-06-22 17:36:49 +08:00
Peng Tao 828204c1cf enable kvm and devmem in guest kernel
Also rebase to 4.4.12 release.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-06-08 11:33:02 +08:00
Gao feng 94720f4ace Merge pull request #116 from laijs/exec_process
introduce hyper_exec_process()
2016-06-06 10:34:04 +08:00
Gao feng 12a797cb9e Merge pull request #117 from feiskyer/redirect
Do not add redirect rule if hostport is equal to containerport
2016-06-06 10:26:55 +08:00
Pengfei Ni 7856628d8a Do not add redirect rule if hostport is equal to containerport 2016-06-06 10:06:18 +08:00
Lai Jiangshan 193c1cc97e introduce hyper_exec_process()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:25:21 +08:00
Lai Jiangshan c3eee6616f remove container_setup_tty()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:21:24 +08:00
Lai Jiangshan 3d57690daa send READY a little earlier when creating container
the flush(stdout) is removed, because it is also called
in the following code hyper_dup_exec_tty().

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:21:24 +08:00
Lai Jiangshan 9ca23869fc split container_setup_workdir()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:21:24 +08:00
Lai Jiangshan 72996cd5e8 make hyper_enter_container() static
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:21:24 +08:00
Lai Jiangshan ab6ff1d2bd setup the exec env in hyper_do_exec_cmd()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:21:08 +08:00
Lai Jiangshan 40f04580ec chdir to the specific dir
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-06-05 23:20:15 +08:00
Gao feng 286e0f9c8f Merge pull request #114 from feiskyer/pm
Add external network white list for port mapping
2016-06-03 16:42:07 +08:00
Pengfei Ni 6aa71c3bd9 Fix syntax errors 2016-06-03 16:39:54 +08:00
Pengfei Ni 01a958b209 add external network white list for port mapping 2016-06-03 16:03:02 +08:00
Lai Jiangshan bbba8776ff Merge pull request #113 from ptptptptptpt/cp_kernel_config
cp kernel_config out after making kernel
2016-06-03 14:40:20 +08:00
Pei Tong 34b6af632a cp kernel_config out after making kernel 2016-06-03 14:20:51 +08:00
Lai Jiangshan 99c593a8be Merge pull request #110 from ptptptptptpt/update-kernel
update kernel to 4.4.11; add more kernel modules
2016-05-31 22:54:09 +08:00
Pei Tong 57b130adbb update kernel to 4.4.11; add more kernel modules: netfilter, overlayfs, dm_thin, etc.. 2016-05-31 10:42:03 +00:00
Pengfei Ni 558adb04ab Merge pull request #109 from laijs/modules_directory
add missing modules/ directory
2016-05-30 16:55:36 +08:00
Lai Jiangshan 684dd342d7 add missing modules/ directory
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-05-30 15:04:42 +08:00
Lai Jiangshan 53bdafd2c5 Merge pull request #107 from gao-feng/route
handle null route json message
2016-05-30 11:11:28 +08:00
Gao feng f54f77ccaa Merge pull request #100 from feiskyer/port-mapping
Add port mapping
2016-05-30 09:27:22 +08:00
Pengfei Ni 6065205cb2 tiny fix 2016-05-29 09:19:06 +00:00
Pengfei Ni 071a0c2b30 Enable icmp by default 2016-05-29 09:19:06 +00:00
Pengfei Ni c4f9764556 Reduce size of iptables command 2016-05-29 09:19:06 +00:00
Pengfei Ni 99fe992d31 Use tcp/udp module instead of multiport 2016-05-29 09:19:06 +00:00
Pengfei Ni 837016a417 Compare string by strncmp 2016-05-29 09:19:06 +00:00
Pengfei Ni d7dd250195 Config protocol for redirect rules 2016-05-29 09:19:06 +00:00
Pengfei Ni 8626dfc79e Add libm for iptables cmd 2016-05-29 09:19:06 +00:00
Pengfei Ni 75e23882bf Setup port mapping for containers 2016-05-29 09:18:30 +00:00
Pengfei Ni 95394c8e5a Add iptables setup for port mapping 2016-05-29 09:18:30 +00:00
Pengfei Ni 623d667fa0 Add iptables cmd 2016-05-29 09:18:30 +00:00
Pengfei Ni 7279227474 Add white cidrs for port-mapping 2016-05-29 09:17:12 +00:00
Gao feng d2daea2927 Merge pull request #108 from laijs/kernel-build
update kernel build
2016-05-27 19:25:34 +08:00
Lai Jiangshan f4493e59f9 update kernel build
build kernel/modules in the hyperstart-dev:latest container
remove build/modules/ directroy and add modules.tar instead

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-05-27 18:29:03 +08:00
Gao feng 9cca6ef2f9 handle null route json message
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-26 15:38:00 +08:00
Lai Jiangshan aea6029ba1 Merge pull request #105 from gao-feng/route
support setup routes separately
2016-05-25 21:23:20 +08:00
Xu Wang fcc973cda6 Merge pull request #106 from gnawux/release_06
bump version to 0.6.0
2016-05-25 19:35:33 +08:00
Gao feng 0896a874c7 fix incorrect error message
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-25 15:31:36 +08:00
Gao feng 53ffb48e0a support setup routes separately
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-25 15:31:34 +08:00
Xu Wang a70c3cfb54 bump version to 0.6.0 2016-05-25 14:44:33 +08:00
Xu Wang 1a4a6794e0 Merge pull request #86 from bergwolf/9p-getattr
9p getattr hack
2016-05-25 12:53:31 +08:00
Lai Jiangshan 8024730027 Merge pull request #104 from gao-feng/fd
close fd in hyper_create
2016-05-24 16:08:35 +08:00
Gao feng 211eb96eb6 close fd in hyper_create
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-24 15:59:17 +08:00
Lai Jiangshan 5b7069c8b4 Merge pull request #102 from laijs/HOME-env
set the HOME env correctly when it is not configured
2016-05-20 07:57:27 +08:00
Lai Jiangshan ece6aa1a79 set the HOME env correctly when it is not configured
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-05-19 20:36:04 +08:00
Lai Jiangshan 185cfb9fe4 Merge pull request #95 from gao-feng/interface
support setup interface command
2016-05-19 14:02:38 +08:00
Gao feng c8b2fee21c Merge pull request #99 from gao-feng/fix
podinit: wait until container environment is ready
2016-05-18 14:56:00 +08:00
Gao feng 9ce56b757e podinit: wait until container environment is ready
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-18 14:48:11 +08:00
Gao feng 72fc9ade82 Merge pull request #98 from gao-feng/exit
use _exit replace exit
2016-05-18 12:33:02 +08:00
Gao feng 05c85499bc use _exit replace exit
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-18 12:32:11 +08:00
Lai Jiangshan 3785a4d02c Merge pull request #94 from gao-feng/exit
make exit code of exec/container consist with docker
2016-05-17 23:17:13 +08:00
Gao feng d74aaa326d make exit code of exec/container consist with docker
The exit code from `docker run` gives information about why the container
failed to run or why it exited.  When `docker run` exits with a non-zero code,
the exit codes follow the `chroot` standard, see below:

**_125_** if the error is with Docker daemon **_itself_**

    $ docker run --foo busybox; echo $?
    # flag provided but not defined: --foo
      See 'docker run --help'.
      125

**_126_** if the **_contained command_** cannot be invoked

    $ docker run busybox /etc; echo $?
    # docker: Error response from daemon: Container command '/etc' could not be invoked.
      126

**_127_** if the **_contained command_** cannot be found

    $ docker run busybox foo; echo $?
    # docker: Error response from daemon: Container command 'foo' not found or does not exist.
      127

**_Exit code_** of **_contained command_** otherwise

    $ docker run busybox /bin/sh -c 'exit 3'; echo $?
    # 3

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-17 15:33:24 +08:00
Gao feng 9615c24fca reagrd exec/start-container success after fork/clone success
If fork/clone failed, return ERROR message to outside.
otherwise ragard exec/start-container success, add
container/exec to exec list, waitpid in init will get
the exec status.

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-17 15:33:01 +08:00
Lai Jiangshan 783d711be1 Merge pull request #96 from gao-feng/init-exit
kill processes in container if container init exited
2016-05-17 15:08:11 +08:00
Gao feng 30b3bf772b kill processes in container if container init exited
consist with docker behavior.

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-17 11:13:20 +08:00
Lai Jiangshan d69a74be22 Merge pull request #90 from laijs/user
enable the user config
2016-05-16 22:31:19 +08:00
Lai Jiangshan 908797e672 enable the user config
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-05-13 16:34:40 +08:00
Gao feng cf2267cff2 support setup interface command
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-05-12 16:40:56 +08:00
Lai Jiangshan 42ba6daf6d Merge pull request #91 from WeiZhang555/typo
Fix typo
2016-05-10 18:11:06 +08:00
Zhang Wei 61b2963d0d Fix typo
Signed-off-by: Zhang Wei <zhangwei555@huawei.com>
2016-05-10 16:36:50 +08:00
Peng Tao c92d2d6430 Merge pull request #87 from laijs/fix-double-free
fix double free bug
2016-05-05 09:26:24 +08:00
Lai Jiangshan 274fa5cd84 fix double free bug
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-05-05 00:33:05 +08:00
Peng Tao baa07ce3f9 9p getattr hack
Update kernel to include 9p's getattr hack to make
fstat after unlink work.

The extra patch is in the kernel_patch directory.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-05-04 23:21:51 +08:00
Peng Tao 402a930af0 Merge pull request #85 from bergwolf/strdup
fix a few strdup memory leaks
2016-04-29 15:37:57 +08:00
Peng Tao 4475e2db1b fix possible memory leak
We are overriding container->image when passed container->scsiaddr. Make
sure we also free its memory if caller also passes the image field.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-04-29 15:36:28 +08:00
Peng Tao 2c12120713 fix two strdup memory leak
Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-04-29 15:36:14 +08:00
Gao feng 84207a3f97 Merge pull request #84 from laijs/allow-container_setup_modules-failed
Allow container_setup_modules() failed
2016-04-29 00:43:50 -05:00
Lai Jiangshan ab1c293818 extend the stack for hyper_container_init()
container_setup_modules() needs a large stack

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-27 21:46:03 +08:00
Lai Jiangshan 3fbba94a0f ignore error of setup modules
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-27 20:22:42 +08:00
Gao feng a9b7fed072 Merge pull request #81 from laijs/sync-time
sync hardware time to system time when start pod
2016-04-26 21:36:40 -05:00
Gao feng ad196e2fe3 Merge pull request #83 from bergwolf/xfs
xfs needs nouuid mount option
2016-04-25 21:09:35 -05:00
Peng Tao 0c3b80fdbd xfs needs nouuid mount option
Otherwise devicemapper/rbd mount might fail due to device UUID
conflicts on snapshot/clone devices.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-04-25 22:08:43 +08:00
Lai Jiangshan c835eb9dfe sync hardware time to system time when start pod
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-25 18:17:06 +08:00
Gao feng 99319c29a6 Merge pull request #79 from gao-feng/module
Add useful modules for hyper container
2016-04-22 20:43:38 -05:00
Gao feng 354c4f44b6 Add useful modules for hyper container
Add cgroup, netfilter, tun, veth and rtc driver.

Note: In some case, kernel will try to use userspace modprobe to
load module, so make sure init mntns has modprobe and modules.

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-20 17:46:32 +08:00
Gao feng 048ee7ba27 Merge pull request #75 from gao-feng/volume
fix fail to populate volume created by sharefs
2016-04-19 23:37:30 -05:00
Xu Wang 9eef10d3c3 Merge pull request #78 from laijs/hyperd-address
update the github address of the hypercontainer
2016-04-19 00:13:50 +08:00
Lai Jiangshan ecdc3cd339 update the github address of the hypercontainer
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-19 00:07:24 +08:00
Xu Wang 4f5b747c2b Merge pull request #76 from bergwolf/setup_dns
recreate /etc/resolv.conf iff specified in pod spec
2016-04-18 18:28:25 +08:00
Peng Tao a0bc0851d6 recreate /etc/resolv.conf iif specified in pod spec
hyperd would inject a default DNS server if user did not specify
it in pod spec. If we recreate resolv.conf here, the injected file
will be lost.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-04-17 17:37:52 +08:00
Gao feng c68c7b76d1 fix fail to populate volume created by sharefs
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-16 13:46:13 +08:00
Gao feng 9590958aae Merge pull request #70 from laijs/fix-exec-part2-update-API-between-runv-and-hyperstart
Fix exec part2 update api between runv and hyperstart
2016-04-07 21:03:54 -05:00
Lai Jiangshan d3199fcc60 remove defautl setting on tty when exec
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-07 16:45:56 +08:00
Lai Jiangshan 4b45b28122 use VmProcess and hyper_parse_process() for exec
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-07 15:11:38 +08:00
Lai Jiangshan e458707966 add hyper_parse_process() for parsing VmProcess
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-07 14:26:13 +08:00
Gao feng 3554b8ef0b Merge pull request #69 from laijs/fix-exec-part1-cleanup
Fix exec part1 cleanup
2016-04-07 00:44:25 -05:00
Lai Jiangshan 48e7b27737 rename container_parse_cmd() to container_parse_argv()
and take struct hyper_exec as its first argument.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-07 12:17:50 +08:00
Lai Jiangshan 1cff207e67 kill all exec rather than only container in hyper_term_all()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 15:03:52 +08:00
Lai Jiangshan aa50e5812b move envs to struct hyper_exec
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 14:59:08 +08:00
Lai Jiangshan 64cbfd2a0b move workdir to struct hyper_exec
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 14:19:15 +08:00
Lai Jiangshan e487303205 rename container_free_cmd() to container_cleanup_exec()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 13:56:11 +08:00
Lai Jiangshan 5a91148a37 remove unused var path
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 12:52:25 +08:00
Lai Jiangshan 6a56562120 require exec->seq be set, we can't handle zero seq well
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 12:06:04 +08:00
Lai Jiangshan 8803fa8ccb move symlink of devices to container_setup_mount()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-06 10:35:50 +08:00
Lai Jiangshan 90998a9b21 Merge pull request #67 from bergwolf/no-init
recreate docker init layer files
2016-04-05 10:56:17 +08:00
Peng Tao 5e945d507e recreate docker init layer files
So that it is possible for the container creation code to skip
the init layer all together.

Signed-off-by: Peng Tao <bergwolf@gmail.com>
2016-04-05 03:09:53 +08:00
Lai Jiangshan c1023f414f Merge pull request #68 from gao-feng/copy
Copy
2016-04-04 23:58:21 +08:00
Gao feng e737392fc4 copy: symlink sh and tar to busybox
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-04 23:22:42 +08:00
Gao feng 01a09c9b8f copy: remove .oldroot prefix for busybox path
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-04 23:20:56 +08:00
Gao feng a524b04f8c copy: return error when exec copy failed
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-04 23:20:23 +08:00
Gao feng 2332d39620 Merge pull request #66 from laijs/setup-rootfs-before-chroot
Setup mounts&rootfs before chroot
2016-04-04 10:18:19 -05:00
Lai Jiangshan bc28dfedf8 remove prefix from hyper_find_sd()
we always use the intial /sys, so we don't need prefix

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-03 22:47:09 +08:00
Lai Jiangshan 09c0a1b41b remove oldroot
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-03 22:41:27 +08:00
Lai Jiangshan b441c1bffe do container_setup_dns() before move the rootfs
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-03 19:09:11 +08:00
Lai Jiangshan 5be2a71a84 do container_setup_volume() before move the rootfs
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-03 16:52:14 +08:00
Lai Jiangshan 8766f77f24 do container_setup_mount() before move the rootfs
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-03 16:34:08 +08:00
Lai Jiangshan e4beaad672 Merge pull request #65 from gao-feng/nondocker
create volume directory for non docker volume
2016-04-03 13:39:42 +08:00
Gao feng 7f6056fc4c create volume directory for non docker volume
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-03 12:26:24 +08:00
Lai Jiangshan 5ceb9b8906 Merge pull request #64 from gao-feng/volume
don't copy data to volume if volume alreay has data
2016-04-02 22:09:35 +08:00
Gao feng 2ace93e881 don't copy data to volume if volume alreay has data
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-02 20:22:51 +08:00
Gao feng abd52a4ae2 Merge pull request #63 from laijs/remove-oldroot-from-mount-source
Remove '/.oldroot' from mount source
2016-04-02 05:22:59 -05:00
Lai Jiangshan 76bccbd261 remove "/.oldroot" from mount source
before patch:
root@test-container-multi:/# mount
/dev/sdb on / type xfs (rw,relatime,attr2,inode64,logbsize=64k,sunit=128,swidth=128,noquota)
/.oldroot/dev/sda on /var/log type ext4 (rw,relatime,stripe=16,data=ordered)

after patch:
root@test-container-multi:/# mount
/dev/sdb on / type xfs (rw,relatime,attr2,inode64,logbsize=64k,sunit=128,swidth=128,noquota)
/dev/sda on /var/log type ext4 (rw,relatime,stripe=16,data=ordered)

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 17:52:25 +08:00
Lai Jiangshan 8f70de4d49 change the order of basic mount and volume mount
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 17:46:51 +08:00
Lai Jiangshan ea196f786d move mount of fsmap into container_setup_volume()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 17:41:55 +08:00
Gao feng ced3b9dc53 Merge pull request #62 from laijs/mkdir
print mkdir info in correct order
2016-04-02 01:04:35 -05:00
Gao feng 5ca0595e4f Merge pull request #61 from laijs/ptys
fix symlink leek
2016-04-02 01:04:19 -05:00
Gao feng 53cd58a121 Merge pull request #60 from laijs/msmove
Set the rootfs of the namespace to be the rootfs of the container
2016-04-01 23:05:40 -05:00
Lai Jiangshan 0a86f73869 Set the rootfs of the namespace to be the rootfs of the container
we use MS_MOVE to move the container rootfs to /, so that the rootfs
of the namespace and the rootfs of the container are the same.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 11:54:14 +08:00
Lai Jiangshan 12ba0a42b2 print mkdir info in correct order
and only print it when it is needed to be maked.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 11:37:06 +08:00
Lai Jiangshan 1ad3ffcf63 close ptymaster before exec
ptymaster is dup-ed without close-on-exec, we need to colse it.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 11:29:15 +08:00
Lai Jiangshan 5f9a7ee0a2 reopen slave ptyfd for correcting the symlink path of the /dev/fd/1
before patch:
root@ubuntu-4562002641:/# readlink /dev/fd/1
/tmp/hyper/656f914cd9c030214bf95aff8f3bf418c1c277f5b82a661a27a174c9c8ce901b/devpts/3

after patch:
root@ubuntu-5512501784:/# readlink /dev/fd/1
/dev/pts/1

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-02 11:10:48 +08:00
Gao feng b0c0255148 Merge pull request #58 from gao-feng/initialize
support to initialize container environment
2016-04-01 21:48:51 -05:00
Gao feng 6b67c6a296 Merge pull request #59 from laijs/mount-rootfs
ensure the container see the mount point of the rootfs
2016-04-01 05:54:48 -05:00
Lai Jiangshan 0017a6110f ensure the container see the mount point of the rootfs
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-04-01 18:28:32 +08:00
Gao feng 6bbb9ac512 support to initialize container environment
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-04-01 16:48:26 +08:00
Xu Wang 6feb864e30 Merge pull request #57 from feiskyer/fix-cache
Do not cache for shared volumes
2016-03-29 11:34:50 +08:00
feisky 6ff04bf83d Do not cache for shared volumes 2016-03-28 17:45:00 +08:00
Lai Jiangshan 80778ddd25 Merge pull request #56 from laijs/pipe2
convert hyper_socketpair() to pipe2
2016-03-28 08:15:03 +08:00
Lai Jiangshan c455e8bc75 convert hyper_socketpair() to pipe2
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-26 18:23:03 +08:00
feisky 411cffdeec Merge pull request #55 from laijs/env
fix up default environment
2016-03-26 12:12:01 +08:00
Lai Jiangshan 04689c4138 set HOSTNAME environment
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-26 12:03:15 +08:00
Lai Jiangshan 50928fc1ef set/unset TERM environment based on tty config
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-26 11:44:37 +08:00
Lai Jiangshan 20c34a4312 set HOME environment
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-26 11:39:36 +08:00
Gao feng fdd2634721 Merge pull request #54 from liusdu/typo
fix a tiny typo to avoid compile error
2016-03-19 14:23:00 +00:00
Liu Hua b043ac88e1 fix a tiny typo to avoid compile error
Signed-off-by: Liu Hua <sdu.liu@huawei.com>
2016-03-19 22:03:28 +08:00
Gao feng 5c18914f2a Merge pull request #53 from laijs/handle-eof
Handle eof
2016-03-18 22:25:14 -05:00
Lai Jiangshan a0e1ecb2ba handle eof request of stdin
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-19 10:28:19 +08:00
Lai Jiangshan 5279ef3f96 send eof of stdout back to runv ony when release_exec()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-19 10:27:42 +08:00
feisky 36fb6e6877 Merge pull request #52 from gao-feng/tty
request to setup tty for exec by default
2016-03-15 12:02:54 +08:00
Gao feng 6632db44ae request to setup tty for exec by default
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-03-15 11:36:11 +08:00
feisky 613a5a19db Merge pull request #51 from laijs/pipes-stdio
use pipes for stdio when non tty
2016-03-10 17:13:32 +08:00
Lai Jiangshan 21d63485b1 use pipes for stdio when non tty
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-10 00:14:03 +08:00
Lai Jiangshan eaae1ae3fb split exec.e into exec.stdinev and exec.stdoutev
and rename exec.errev to exec.stderrev
and make stdinev.fd stdoutev.fd stderrev.fd are valid but different
and register all these event

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-09 23:53:59 +08:00
Lai Jiangshan 333263b344 pass @exec to pts_hup()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-09 16:07:53 +08:00
Lai Jiangshan 50db29c634 add stdinfd/stdoutfd and rename errfd to stderrfd
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-09 16:01:17 +08:00
Lai Jiangshan fe5c6c29e1 use e->errfd directly to create stderr
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-09 15:46:04 +08:00
Lai Jiangshan 34d842901d always setup exec->errfd
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-09 15:45:48 +08:00
Lai Jiangshan a94833c482 open /dev/null for ptyfd in hyper_setup_exec_tty() when seq=0
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-09 15:45:37 +08:00
Gao feng 0676ed3227 Merge pull request #50 from laijs/enable-non-tty-stdio
Enable non tty stdio
2016-03-09 10:42:48 +08:00
Lai Jiangshan e12e480f79 change VmContainer's stdio's protocal
VmContainer.Tty: allocate tty or not
VmContainer.Stdio: Stdio sequence number
VmContainer.Stderr: Stderr sequence number if stderr is not share with
stdout (currently used when VmContainer.Tty is false)

And new stdio allocation code which respects the VmContainer.Tty.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-08 21:03:34 +08:00
Lai Jiangshan 3fa27e7464 handle eof for the stdio handling
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-08 21:02:42 +08:00
Lai Jiangshan 013cbb7e1a Merge pull request #49 from laijs/pause
pause() in the pod_init loop
2016-03-07 23:22:52 +08:00
Lai Jiangshan 97aee2acb0 pause() in the pod_init loop
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-07 23:00:17 +08:00
Gao feng 43c2336d7f Merge pull request #48 from laijs/sigchld
Simplify SIGCHLD handling and make it exclusive with event handling
2016-03-07 22:50:44 +08:00
Lai Jiangshan 220677d76d simplify SIGCHLD handling of hyper_init
It uses epoll_pwait() instead of epoll_wait(), and ensures that
the SIGCHLD handling and the events handling are exclusive.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-07 21:42:25 +08:00
Lai Jiangshan 0f396470ff simplify SIGCHLD handling of pod_init
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-07 21:38:52 +08:00
Xu Wang 94266c5111 Merge pull request #47 from laijs/no-nonblock-stderr
remove O_NONBLOCK from stderr
2016-03-06 07:29:56 +08:00
Lai Jiangshan 0b3370f6fa remove O_NONBLOCK from stderr
step1: start a container without tty
	hyper run ubuntu
step2: get the fdinfo of the stderr
	cat /proc/self/fdinfo/2
	pos:	0
	flags:	04001
	mnt_id:	8
it shows that the stderr has the O_NONBLOCK flags,
we should remove it.

Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-03-05 21:49:38 +08:00
Lai Jiangshan c5abeccb65 Merge pull request #46 from laijs/missing-exit
add missing exit(0) to hyper_cmd_online_cpu_mem()
2016-02-29 23:00:12 +08:00
Lai Jiangshan aa7772b36c add missing exit(0) to hyper_cmd_online_cpu_mem()
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-02-29 22:59:05 +08:00
Lai Jiangshan f47d84cf24 Merge pull request #45 from gao-feng/fix-free
free stack after cloned children finished
2016-02-29 18:58:51 +08:00
Gao feng d97485cfc0 free stack after cloned children finished
avoid children using the freed memory.

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-02-26 14:53:40 +08:00
Lai Jiangshan 4fc4ac0c46 Merge pull request #44 from laijs/online-cpu-mem
add ONLINECPUMEM command
2016-02-22 10:04:34 +08:00
Lai Jiangshan bd41fcfbe6 add ONLINECPUMEM command
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-02-19 13:31:07 +08:00
Gao feng bd9623c892 Merge pull request #43 from gnawux/release-0.5
release hyper/runv 0.5
2016-02-05 15:46:51 +08:00
Xu Wang 00e65b239c release hyper/runv 0.5
Signed-off-by: Xu Wang <gnawux@gmail.com>
2016-02-05 15:42:36 +08:00
Lai Jiangshan b654a0fbd3 Merge pull request #42 from gao-feng/free
fix possible access memory after free
2016-02-01 10:56:40 +08:00
Gao feng 2f757d249d Merge pull request #41 from gnawux/resize_cbfs
new kernel is bigger, increase the cbfs rom size
2016-01-31 21:22:45 +08:00
Gao feng db33f31dc1 fix possible access memory after free
For tasks created by clone_VM, they share the memory with parent,
so when parent frees the stack, children may still access to this
stack. so don't free stack when children is still using the stack.

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-01-31 19:24:07 +08:00
Wang Xu 661dcdda07 new kernel is bigger, increase the cbfs rom size
Signed-off-by: Wang Xu <gnawux@gmail.com>
2016-01-30 23:42:06 +08:00
Gao feng 22a65f7666 Merge pull request #40 from laijs/hot-add-cpu-mem
enable hot adding cpu/mem
2016-01-28 15:51:17 +08:00
Lai Jiangshan 1ce35da941 enable hot adding cpu/mem
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-01-28 15:48:43 +08:00
Xu Wang e6cffd9add Merge pull request #39 from laijs/escape
handle all escaped character correctly
2016-01-16 08:04:50 +08:00
Lai Jiangshan 213a00ec5e handle all escaped character correctly
Signed-off-by: Lai Jiangshan <jiangshanlai@gmail.com>
2016-01-15 22:36:12 +08:00
Lai Jiangshan c03c057a42 Merge pull request #37 from gao-feng/escape
handle escaped characters
2016-01-15 21:59:44 +08:00
Gao feng 73849713e8 handle escaped characters
./hyper run --rm ubuntu echo xxxx\>\"\\aadasd\"\>\<\>\<\<\<\\\\\\\"\as
POD id is pod-nvpvjBScdB
xxxx>"\aadasd"><><<<\\\"as

echo xxxx\>\"\\aadasd\"\>\<\>\<\<\<\\\\\\\"\as
xxxx>"\aadasd"><><<<\\\"as

Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-01-14 11:12:33 +08:00
Lai Jiangshan 0610a4e156 Merge pull request #31 from gao-feng/exit
send out exec exit code
2016-01-07 16:44:17 +08:00
Gao feng 29efaadf0a send out exec exit code
Signed-off-by: Gao feng <omarapazanadi@gmail.com>
2016-01-06 00:12:30 +08:00
33 changed files with 6136 additions and 1447 deletions
+1
View File
@@ -14,6 +14,7 @@ build/cbfs.rom
build/root/* build/root/*
build/*iso build/*iso
build/daemon build/daemon
build/kernel_config.old
build/.* build/.*
src/.* src/.*
Makefile Makefile
+2
View File
@@ -4,3 +4,5 @@ initrd-local:
@echo finish make initrd @echo finish make initrd
cbfs-local: cbfs-local:
@echo finish make cbfs @echo finish make cbfs
kernel-local:
@echo finish make kernel
+2 -2
View File
@@ -1,6 +1,6 @@
# The init Task for Hyper # The init Task for HyperContainer
You can get the binary installer of Hyper and HyperStart through [The Hyper Page](https://github.com/hyperhq/hyper) You can get the binary installer of HyperContainer and HyperStart through [The Hyper Page](https://github.com/hyperhq/hyperd)
## Build from source ## Build from source
+29
View File
@@ -0,0 +1,29 @@
FROM centos:7
MAINTAINER Hyper Developers <dev@hyper.sh>
RUN yum install -y patch gcc ncurses-devel make openssl-devel bc
ENV KERNEL_VERSION 4.4.12
ENV LOCALVERSION -hyper
ENV KERNEL_RELEASE ${KERNEL_VERSION}${LOCALVERSION}
ENV KBUILD_BUILD_USER dev
ENV KBUILD_BUILD_HOST hyper.sh
ENV KBUILD_BUILD_VERSION 1
RUN mkdir /root/build/ && mkdir /root/build/result/
RUN curl -fSL https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-${KERNEL_VERSION}.tar.gz | tar -zx -C /root/build
COPY kernel_config /root/build/linux-${KERNEL_VERSION}/.config
COPY kernel_patch/ /root/build/kernel_patch/
RUN cd /root/build/linux-${KERNEL_VERSION}/ && for patch in /root/build/kernel_patch/*.patch; do patch -p1 <$patch || exit 1; done
RUN cd /root/build/linux-${KERNEL_VERSION}/ && make silentoldconfig && make -j 8
# install to /root/build/result/ so that we can get them from it
RUN cp /root/build/linux-${KERNEL_VERSION}/arch/x86_64/boot/bzImage /root/build/result/kernel
RUN mkdir /root/build/result/modules &&\
cd /root/build/linux-${KERNEL_VERSION}/ && make modules_install INSTALL_MOD_PATH="/root/build/result/modules" &&\
cd /root/build/result/modules/lib/modules/ && rm -f ${KERNEL_RELEASE}/{build,source} &&\
tar -cf /root/build/result/modules.tar ${KERNEL_RELEASE}/ && rm -rf /root/build/result/modules
RUN cp /root/build/linux-${KERNEL_VERSION}/.config /root/build/result/kernel_config
+7
View File
@@ -10,3 +10,10 @@ endif
cbfs-local: cbfs-local:
bash ./make-initrd.sh cbfs bash ./make-initrd.sh cbfs
kernel-local:
hyperctl build -t hyperstart-dev:latest .
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/kernel >kernel.new && mv -f kernel.new kernel
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/modules.tar >modules.tar
mv kernel_config kernel_config.old
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/kernel_config >kernel_config
Executable
BIN
View File
Binary file not shown.
Executable
BIN
View File
Binary file not shown.
BIN
View File
Binary file not shown.
+916 -215
View File
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,43 @@
From 084b4a5aa4b90975f7ac6b4714a6b449430ef4c4 Mon Sep 17 00:00:00 2001
From: Peng Tao <bergwolf@gmail.com>
Date: Wed, 4 May 2016 12:01:22 +0800
Subject: [PATCH] HACK: 9P: always use cached inode to fill in v9fs_vfs_getattr
So that if in cache=none mode, we don't have to lookup server that
might not support open-unlink-fstat operation.
Signed-off-by: Peng Tao <bergwolf@gmail.com>
---
fs/9p/vfs_inode.c | 2 +-
fs/9p/vfs_inode_dotl.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/fs/9p/vfs_inode.c b/fs/9p/vfs_inode.c
index 5110785..43ebb31 100644
--- a/fs/9p/vfs_inode.c
+++ b/fs/9p/vfs_inode.c
@@ -1059,7 +1059,7 @@ v9fs_vfs_getattr(struct vfsmount *mnt, struct dentry *dentry,
p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
v9ses = v9fs_dentry2v9ses(dentry);
- if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
+ if (!d_really_is_negative(dentry) || v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
generic_fillattr(d_inode(dentry), stat);
return 0;
}
diff --git a/fs/9p/vfs_inode_dotl.c b/fs/9p/vfs_inode_dotl.c
index cb899af..b1e4205 100644
--- a/fs/9p/vfs_inode_dotl.c
+++ b/fs/9p/vfs_inode_dotl.c
@@ -479,7 +479,7 @@ v9fs_vfs_getattr_dotl(struct vfsmount *mnt, struct dentry *dentry,
p9_debug(P9_DEBUG_VFS, "dentry: %p\n", dentry);
v9ses = v9fs_dentry2v9ses(dentry);
- if (v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
+ if (!d_really_is_negative(dentry) || v9ses->cache == CACHE_LOOSE || v9ses->cache == CACHE_FSCACHE) {
generic_fillattr(d_inode(dentry), stat);
return 0;
}
--
2.5.0
BIN
View File
Binary file not shown.
+13 -9
View File
@@ -1,18 +1,22 @@
#!/bin/bash #!/bin/bash
rm -rf root rm -rf /tmp/hyperstart-rootfs
mkdir root mkdir -p /tmp/hyperstart-rootfs/lib /tmp/hyperstart-rootfs/lib64 /tmp/hyperstart-rootfs/lib/modules
cp ../src/init ./root cp ../src/init /tmp/hyperstart-rootfs
cp busybox /tmp/hyperstart-rootfs
cp iptables /tmp/hyperstart-rootfs
cp libm.so.6 /tmp/hyperstart-rootfs/lib64/
tar -xf modules.tar -C /tmp/hyperstart-rootfs/lib/modules
ldd ./root/init | while read line ldd /tmp/hyperstart-rootfs/init | while read line
do do
arr=(${line// / }) arr=(${line// / })
for lib in ${arr[@]} for lib in ${arr[@]}
do do
if [ "${lib:0:1}" = "/" ]; then if [ "${lib:0:1}" = "/" ]; then
dir=root`dirname $lib` dir=/tmp/hyperstart-rootfs`dirname $lib`
mkdir -p "${dir}" mkdir -p "${dir}"
cp -f $lib $dir cp -f $lib $dir
fi fi
@@ -21,13 +25,13 @@ done
if [ "$1"x = "vbox"x ]; then if [ "$1"x = "vbox"x ]; then
echo "build initrd for vbox" echo "build initrd for vbox"
cp ./vbox/driver/* ./root cp ./vbox/driver/* /tmp/hyperstart-rootfs
fi fi
cd ./root && find . | cpio -H newc -o | gzip -9 > ../hyper-initrd.img ( cd /tmp/hyperstart-rootfs && find . | cpio -H newc -o | gzip -9 ) > ./hyper-initrd.img
cd ../ cd ../
rm -rf ./root rm -rf /tmp/hyperstart-rootfs
if [ "$1"x = "cbfs"x ]; then if [ "$1"x = "cbfs"x ]; then
echo "build cbfs" echo "build cbfs"
@@ -36,7 +40,7 @@ if [ "$1"x = "cbfs"x ]; then
mkdir .cbfs mkdir .cbfs
dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1 dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1
cbfstool .cbfs/cbfs.rom create -s 4096k -B .cbfs/boot.bin -m x86 0x1000 cbfstool .cbfs/cbfs.rom create -s 8128k -B .cbfs/boot.bin -m x86 0x1000
cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw
cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw
echo 'console=ttyS0 panic=1 no_timer_check' > .cbfs/cmdline echo 'console=ttyS0 panic=1 no_timer_check' > .cbfs/cmdline
BIN
View File
Binary file not shown.
+2 -2
View File
@@ -2,9 +2,9 @@
# Process this file with autoconf to produce a configure script. # Process this file with autoconf to produce a configure script.
AC_PREREQ([2.69]) AC_PREREQ([2.69])
AC_INIT([hyperstart], [0.3], [www.hyper.sh]) AC_INIT([hyperstart], [0.6.2], [www.hyper.sh])
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects]) AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
AM_EXTRA_RECURSIVE_TARGETS([initrd cbfs]) AM_EXTRA_RECURSIVE_TARGETS([initrd cbfs kernel])
AC_CONFIG_SRCDIR([src/init.c]) AC_CONFIG_SRCDIR([src/init.c])
AC_CONFIG_HEADERS([config.h]) AC_CONFIG_HEADERS([config.h])
+1 -1
View File
@@ -1,3 +1,3 @@
AM_CFLAGS = -Wall AM_CFLAGS = -Wall
bin_PROGRAMS=init bin_PROGRAMS=init
init_SOURCES=init.c jsmn.c net.c util.c parse.c container.c exec.c event.c init_SOURCES=init.c jsmn.c net.c util.c parse.c parson.c container.c exec.c event.c portmapping.c
+399 -242
View File
@@ -7,6 +7,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/utsname.h>
#include <unistd.h> #include <unistd.h>
#include <mntent.h> #include <mntent.h>
#include <signal.h> #include <signal.h>
@@ -19,6 +20,79 @@
#include "parse.h" #include "parse.h"
#include "syscall.h" #include "syscall.h"
static int container_populate_volume(char *src, char *dest)
{
struct stat st;
fprintf(stdout, "populate volumes from %s to %s\n", src, dest);
/* FIXME: check if has data in volume, (except lost+found) */
if (stat(dest, &st) == 0) {
if (!S_ISDIR(st.st_mode)) {
fprintf(stderr, "the _data in volume %s is not directroy\n", dest);
return -1;
}
return 0;
}
if (errno != ENOENT) {
perror("access to volume failed\n");
return -1;
}
if (hyper_mkdir(dest, 0777) < 0) {
fprintf(stderr, "fail to create directroy %s\n", dest);
return -1;
}
return hyper_copy_dir(src, dest);
}
const char *INIT_VOLUME_FILENAME = ".hyper_file_volume_data_do_not_create_on_your_own";
static int container_check_file_volume(char *hyper_path, const char **filename)
{
struct dirent **list;
struct stat stbuf;
int i, num, found = 0;
char path[PATH_MAX];
*filename = NULL;
num = scandir(hyper_path, &list, NULL, NULL);
if (num < 0) {
/* No data in the volume yet, treat as non-file-volume */
if (errno == ENOENT) {
return 0;
}
perror("scan path failed");
return -1;
} else if (num != 3) {
fprintf(stdout, "%s has %d files/dirs\n", hyper_path, num - 2);
for (i = 0; i < num; i++) {
free(list[i]);
}
free(list);
return 0;
}
sprintf(path, "%s/%s", hyper_path, INIT_VOLUME_FILENAME);
for (i = 0; i < num; i++) {
if (strcmp(list[i]->d_name, ".") != 0 &&
strcmp(list[i]->d_name, "..") != 0 &&
strcmp(list[i]->d_name, INIT_VOLUME_FILENAME) == 0 &&
stat(path, &stbuf) == 0 && S_ISREG(stbuf.st_mode)) {
found++;
}
free(list[i]);
}
free(list);
fprintf(stdout, "%s %s a file volume\n", hyper_path, found > 0?"is":"is not");
*filename = found > 0 ? INIT_VOLUME_FILENAME : NULL;
return 0;
}
static int container_setup_volume(struct hyper_container *container) static int container_setup_volume(struct hyper_container *container)
{ {
int i; int i;
@@ -26,140 +100,113 @@ static int container_setup_volume(struct hyper_container *container)
struct volume *vol; struct volume *vol;
for (i = 0; i < container->vols_num; i++) { for (i = 0; i < container->vols_num; i++) {
char volume[512];
char mountpoint[512];
char *options = NULL;
const char *filevolume = NULL;
vol = &container->vols[i]; vol = &container->vols[i];
if (vol->scsiaddr) if (vol->scsiaddr)
hyper_find_sd("/.oldroot", vol->scsiaddr, &vol->device); hyper_find_sd(vol->scsiaddr, &vol->device);
sprintf(dev, "/.oldroot/dev/%s", vol->device); sprintf(dev, "/dev/%s", vol->device);
sprintf(path, "/tmp/%s", vol->mountpoint); sprintf(path, "/tmp/%s", vol->mountpoint);
sprintf(mountpoint, "./%s", vol->mountpoint);
fprintf(stdout, "mount %s to %s, tmp path %s\n", fprintf(stdout, "mount %s to %s, tmp path %s\n",
dev, vol->mountpoint, path); dev, vol->mountpoint, path);
if (hyper_mkdir(path) < 0 || hyper_mkdir(vol->mountpoint) < 0) { if (hyper_mkdir(path, 0755) < 0) {
perror("create volume dir failed"); perror("create volume dir failed");
return -1; return -1;
} }
if (mount(dev, path, vol->fstype, 0, NULL) < 0) { if (!strncmp(vol->fstype, "xfs", strlen("xfs")))
perror("mount volume device faled"); options = "nouuid";
if (mount(dev, path, vol->fstype, 0, options) < 0) {
perror("mount volume device failed");
return -1; return -1;
} }
if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) { sprintf(volume, "/%s/_data", path);
perror("mount volume device faled"); if (container_check_file_volume(volume, &filevolume) < 0)
return -1;
if (filevolume == NULL) {
if (hyper_mkdir(mountpoint, 0755) < 0) {
perror("create volume dir failed");
return -1;
}
if (vol->docker) {
if (container->initialize &&
(container_populate_volume(mountpoint, volume) < 0)) {
fprintf(stderr, "fail to populate volume %s\n", mountpoint);
return -1;
}
} else if (hyper_mkdir(volume, 0777) < 0) {
/* First time mounting an empty volume */
perror("create _data dir failed");
return -1;
}
} else {
hyper_filize(mountpoint);
if (hyper_create_file(mountpoint) < 0) {
perror("create volume file failed");
return -1;
}
sprintf(volume, "/%s/_data/%s", path, filevolume);
/* 0777 so that any user can read/write the new file volume */
if (chmod(volume, 0777) < 0) {
fprintf(stderr, "fail to chmod directroy %s\n", volume);
return -1;
}
}
if (mount(volume, mountpoint, NULL, MS_BIND, NULL) < 0) {
perror("mount volume device failed");
return -1; return -1;
} }
if (vol->readonly && if (vol->readonly &&
mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) { mount(volume, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
perror("mount fsmap faled"); perror("mount fsmap failed");
return -1; return -1;
} }
umount(path); umount(path);
} }
return 0;
}
static void container_unmount_oldroot(char *path)
{
FILE *mtab;
struct mntent *mnt;
char *mntlist[128];
int i;
int n = 0;
char *filesys;
mtab = setmntent("/proc/mounts", "r");
if (mtab == NULL) {
fprintf(stderr, "cannot open /proc/mount");
return;
}
while (n < 128 && (mnt = getmntent(mtab))) {
if (strncmp(mnt->mnt_dir, path, strlen(path)))
continue;
mntlist[n++] = strdup(mnt->mnt_dir);
}
endmntent(mtab);
for (i = n - 1; i >= 0; i--) {
filesys = mntlist[i];
fprintf(stdout, "umount %s\n", filesys);
if (umount(mntlist[i]) < 0 && umount2(mntlist[i],
MNT_DETACH) < 0) {
fprintf(stdout, "umount %s: %s failed\n",
filesys, strerror(errno));
}
}
}
static int container_setup_mount(struct hyper_container *container)
{
int i, fd;
char src[512];
struct fsmap *map;
hyper_mkdir("/proc");
hyper_mkdir("/sys");
hyper_mkdir("/dev");
if (mount("proc", "/proc", "proc", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
mount("sysfs", "/sys", "sysfs", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID, NULL) < 0) {
perror("mount basic filesystem for container failed");
return -1;
}
if (hyper_mkdir("/dev/shm") < 0) {
fprintf(stderr, "create /dev/shm failed\n");
return -1;
}
if (mount("tmpfs", "/dev/shm/", "tmpfs", MS_NOSUID| MS_NODEV, NULL) < 0) {
perror("mount shm failed");
return -1;
}
if (hyper_mkdir("/dev/pts") < 0) {
fprintf(stderr, "create /dev/pts failed\n");
return -1;
}
if (sprintf(src, "/.oldroot/tmp/hyper/%s/devpts", container->id) < 0) {
fprintf(stderr, "get container devpts failed\n");
return -1;
}
if (mount(src, "/dev/pts/", NULL, MS_BIND, NULL) < 0) {
perror("move pts to /dev/pts failed");
return -1;
}
if (unlink("/dev/ptmx") < 0)
perror("remove /dev/ptmx failed");
if (symlink("/dev/pts/ptmx", "/dev/ptmx") < 0)
perror("link /dev/pts/ptmx to /dev/ptmx failed");
for (i = 0; i < container->maps_num; i++) { for (i = 0; i < container->maps_num; i++) {
struct stat st; struct stat st;
char *src, path[512], volume[512];
struct fsmap *map = &container->maps[i];
char mountpoint[512];
map = &container->maps[i]; sprintf(path, "/tmp/hyper/shared/%s", map->source);
sprintf(mountpoint, "./%s", map->path);
sprintf(src, "/.oldroot/tmp/hyper/shared/%s", map->source); fprintf(stdout, "mount %s to %s\n", path, mountpoint);
fprintf(stdout, "mount %s to %s\n", src, map->path);
src = path;
stat(src, &st); stat(src, &st);
if (st.st_mode & S_IFDIR) { if (st.st_mode & S_IFDIR) {
if (hyper_mkdir(map->path) < 0) { if (hyper_mkdir(mountpoint, 0755) < 0) {
perror("create map dir failed"); perror("create map dir failed");
continue; continue;
} }
if (map->docker) {
/* converted from volume */
sprintf(volume, "%s/_data", path);
src = volume;
if (container->initialize &&
(container_populate_volume(mountpoint, volume) < 0)) {
fprintf(stderr, "fail to populate volume %s\n", mountpoint);
continue;
}
}
} else { } else {
fd = open(map->path, O_CREAT|O_WRONLY, 0755); int fd = open(mountpoint, O_CREAT|O_WRONLY, 0755);
if (fd < 0) { if (fd < 0) {
perror("create map file failed"); perror("create map file failed");
continue; continue;
@@ -167,65 +214,201 @@ static int container_setup_mount(struct hyper_container *container)
close(fd); close(fd);
} }
if (mount(src, map->path, NULL, MS_BIND, NULL) < 0) { if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
perror("mount fsmap faled"); perror("mount fsmap failed");
continue; continue;
} }
if (map->readonly == 0) if (map->readonly == 0)
continue; continue;
if (mount(src, map->path, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) if (mount(src, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
perror("mount fsmap faled"); perror("mount fsmap failed");
} }
return 0; return 0;
} }
static int container_setup_modules(struct hyper_container *container)
{
struct stat st;
struct utsname uts;
char src[512], dst[512];
if (uname(&uts) < 0) {
perror("fail to call uname");
return -1;
}
sprintf(src, "/lib/modules/%s", uts.release);
sprintf(dst, "./%s", src);
if (stat(dst, &st) == 0) {
struct dirent **list;
int num;
if (!S_ISDIR(st.st_mode)) {
return -1;
}
num = scandir(dst, &list, NULL, NULL);
if (num > 2) {
fprintf(stdout, "%s is not null, %d", dst, num);
return 0;
}
} else if (errno == ENOENT) {
if (hyper_mkdir(dst, 0755) < 0)
return -1;
} else {
return -1;
}
if (mount(src, dst, NULL, MS_BIND, NULL) < 0) {
perror("mount bind modules failed");
return -1;
}
return 0;
}
static int container_setup_mount(struct hyper_container *container)
{
char src[512];
// current dir is container rootfs, the operations on "./PATH" are the operations on container's "/PATH"
hyper_mkdir("./proc", 0755);
hyper_mkdir("./sys", 0755);
hyper_mkdir("./dev", 0755);
hyper_mkdir("./lib/modules", 0755);
if (mount("proc", "./proc", "proc", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
mount("sysfs", "./sys", "sysfs", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
mount("devtmpfs", "./dev", "devtmpfs", MS_NOSUID, NULL) < 0) {
perror("mount basic filesystem for container failed");
return -1;
}
if (hyper_mkdir("./dev/shm", 0755) < 0) {
fprintf(stderr, "create /dev/shm failed\n");
return -1;
}
if (mount("tmpfs", "./dev/shm/", "tmpfs", MS_NOSUID| MS_NODEV, NULL) < 0) {
perror("mount shm failed");
return -1;
}
if (hyper_mkdir("./dev/pts", 0755) < 0) {
fprintf(stderr, "create /dev/pts failed\n");
return -1;
}
if (sprintf(src, "/tmp/hyper/%s/devpts", container->id) < 0) {
fprintf(stderr, "get container devpts failed\n");
return -1;
}
if (mount(src, "./dev/pts/", NULL, MS_BIND, NULL) < 0) {
perror("move pts to /dev/pts failed");
return -1;
}
if (unlink("./dev/ptmx") < 0)
perror("remove /dev/ptmx failed");
if (symlink("/dev/pts/ptmx", "./dev/ptmx") < 0)
perror("link /dev/pts/ptmx to /dev/ptmx failed");
symlink("/proc/self/fd", "./dev/fd");
symlink("/proc/self/fd/0", "./dev/stdin");
symlink("/proc/self/fd/1", "./dev/stdout");
symlink("/proc/self/fd/2", "./dev/stderr");
return 0;
}
static int container_recreate_file(char *filename)
{
struct stat stbuf;
fprintf(stdout, "recreate file %s\n", filename);
if (stat(filename, &stbuf) < 0) {
if (errno != ENOENT) {
fprintf(stderr, "failed to stat %s: %d\n", filename, errno);
return -1;
}
return hyper_create(filename);
}
if (stbuf.st_mode & S_IFREG && stbuf.st_size == 0)
return 0;
hyper_unlink(filename);
return hyper_create(filename);
}
static int container_recreate_symlink(char *oldpath, char *newpath)
{
fprintf(stdout, "recreate symlink %s to %s\n", newpath, oldpath);
hyper_unlink(newpath);
return hyper_symlink(oldpath, newpath);
}
/*
* Docker uses the init layer to protect against unwanted side effects on
* the rw layer. We recreate the same files here to have similar effect.
* Docker also creates directories like /dev/pts, /dev/shm, /proc, /sys,
* which we have over ridden in container_setup_mount, so no need to create
* them here.
*/
static int container_setup_init_layer(struct hyper_container *container,
int setup_dns)
{
if (!container->initialize)
return 0;
hyper_mkdir("./etc/", 0755);
if (setup_dns && container_recreate_file("./etc/resolv.conf") < 0)
return -1;
if (container_recreate_file("./etc/hosts") < 0)
return -1;
if (container_recreate_file("./etc/hostname") < 0)
return -1;
if (container_recreate_symlink("/proc/mounts", "./etc/mtab") < 0)
return -1;
return 0;
}
static int container_setup_sysctl(struct hyper_container *container) static int container_setup_sysctl(struct hyper_container *container)
{ {
int i, size, len, l, fd; int i;
struct sysctl *sys; struct sysctl *sys;
for (i = 0; i < container->sys_num; i++) { for (i = 0; i < container->sys_num; i++) {
char path[256]; char path[256];
len = 0;
sys = &container->sys[i]; sys = &container->sys[i];
size = strlen(sys->value);
sprintf(path, "/proc/sys/%s", sys->path); sprintf(path, "/proc/sys/%s", sys->path);
fprintf(stdout, "sysctl %s value %s\n", sys->path, sys->value); fprintf(stdout, "sysctl %s value %s\n", sys->path, sys->value);
fd = open(path, O_WRONLY); if (hyper_write_file(path, sys->value, strlen(sys->value)) < 0) {
if (fd < 0) { fprintf(stderr, "sysctl: write %s to %s failed\n", sys->value, path);
perror("open file failed"); return -1;
goto out;
} }
while (len < size) {
l = write(fd, sys->value + len, size - len);
if (l < 0) {
perror("fail to write sysctl");
close(fd);
goto out;
}
len += l;
}
close(fd);
} }
return 0; return 0;
out:
return -1;
} }
static int container_setup_dns(struct hyper_container *container) static int container_setup_dns(struct hyper_container *container)
{ {
int fd; int fd;
struct stat st; struct stat st;
char *src = "/.oldroot/tmp/hyper/resolv.conf"; char *src = "/tmp/hyper/resolv.conf";
if (stat(src, &st) < 0) { if (stat(src, &st) < 0) {
if (errno == ENOENT) { if (errno == ENOENT) {
@@ -237,16 +420,16 @@ static int container_setup_dns(struct hyper_container *container)
return -1; return -1;
} }
hyper_mkdir("/etc"); hyper_mkdir("./etc", 0755);
fd = open("/etc/resolv.conf", O_CREAT| O_WRONLY, 0644); fd = open("./etc/resolv.conf", O_CREAT| O_WRONLY, 0644);
if (fd < 0) { if (fd < 0) {
perror("create /etc/resolv.conf failed"); perror("create /etc/resolv.conf failed");
return -1; return -1;
} }
close(fd); close(fd);
if (mount(src, "/etc/resolv.conf", NULL, MS_BIND, NULL) < 0) { if (mount(src, "./etc/resolv.conf", NULL, MS_BIND, NULL) < 0) {
perror("bind to /etc/resolv.conf failed"); perror("bind to /etc/resolv.conf failed");
return -1; return -1;
} }
@@ -256,19 +439,14 @@ static int container_setup_dns(struct hyper_container *container)
static int container_setup_workdir(struct hyper_container *container) static int container_setup_workdir(struct hyper_container *container)
{ {
if (container->workdir && chdir(container->workdir) < 0) { if (container->initialize) {
perror("change work directory failed"); // create workdir
return -1; return hyper_mkdir(container->exec.workdir, 0755);
} }
return 0; return 0;
} }
static int container_setup_tty(int fd, struct hyper_container *container)
{
return hyper_dup_exec_tty(fd, &container->exec);
}
static int hyper_rescan_scsi(void) static int hyper_rescan_scsi(void)
{ {
struct dirent **list; struct dirent **list;
@@ -316,30 +494,21 @@ static int hyper_rescan_scsi(void)
struct hyper_container_arg { struct hyper_container_arg {
struct hyper_container *c; struct hyper_container *c;
int ipcns; struct hyper_pod *pod;
int utsns;
int pipe[2]; int pipe[2];
int pipens[2];
}; };
static int hyper_container_init(void *data) static int hyper_setup_container_rootfs(void *data)
{ {
struct hyper_container_arg *arg = data; struct hyper_container_arg *arg = data;
struct hyper_container *container = arg->c; struct hyper_container *container = arg->c;
char root[512], oldroot[512]; char root[512], rootfs[512];
int setup_dns;
uint32_t type;
fprintf(stdout, "%s in\n", __func__); if (hyper_enter_sandbox(arg->pod, -1) < 0) {
if (container->exec.argv == NULL) { perror("enter sandbox failed");
fprintf(stdout, "no cmd!\n");
goto fail;
}
if (setns(arg->ipcns, CLONE_NEWIPC) < 0) {
perror("setns to ipcns of pod init faild");
goto fail;
}
if (setns(arg->utsns, CLONE_NEWUTS) < 0) {
perror("setns to ipcns of pod init faild");
goto fail; goto fail;
} }
@@ -348,11 +517,6 @@ static int hyper_container_init(void *data)
goto fail; goto fail;
} }
if (hyper_setup_env(container->envs, container->envs_num) < 0) {
fprintf(stdout, "setup env failed\n");
goto fail;
}
if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) { if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
perror("mount SLAVE failed"); perror("mount SLAVE failed");
goto fail; goto fail;
@@ -364,7 +528,7 @@ static int hyper_container_init(void *data)
} }
sprintf(root, "/tmp/hyper/%s/root/", container->id); sprintf(root, "/tmp/hyper/%s/root/", container->id);
if (hyper_mkdir(root) < 0) { if (hyper_mkdir(root, 0755) < 0) {
perror("make root directroy failed"); perror("make root directroy failed");
goto fail; goto fail;
} }
@@ -373,14 +537,21 @@ static int hyper_container_init(void *data)
if (container->fstype) { if (container->fstype) {
char dev[128]; char dev[128];
char *options = NULL;
if (container->scsiaddr) if (container->scsiaddr) {
hyper_find_sd("", container->scsiaddr, &container->image); free(container->image);
container->image = NULL;
hyper_find_sd(container->scsiaddr, &container->image);
}
sprintf(dev, "/dev/%s", container->image); sprintf(dev, "/dev/%s", container->image);
fprintf(stdout, "device %s\n", dev); fprintf(stdout, "device %s\n", dev);
if (mount(dev, root, container->fstype, 0, NULL) < 0) { if (!strncmp(container->fstype, "xfs", strlen("xfs")))
options = "nouuid";
if (mount(dev, root, container->fstype, 0, options) < 0) {
perror("mount device failed"); perror("mount device failed");
goto fail; goto fail;
} }
@@ -399,26 +570,20 @@ static int hyper_container_init(void *data)
fprintf(stdout, "root directory for container is %s/%s, init task %s\n", fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
root, container->rootfs, container->exec.argv[0]); root, container->rootfs, container->exec.argv[0]);
sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs); sprintf(rootfs, "%s/%s/", root, container->rootfs);
if (hyper_mkdir(oldroot) < 0) { if (mount(rootfs, rootfs, NULL, MS_BIND|MS_REC, NULL) < 0) {
perror("make oldroot directroy failed"); perror("failed to bind rootfs");
goto fail; goto fail;
} }
chdir(rootfs);
if (mount("/", oldroot, NULL, MS_BIND|MS_REC, NULL) < 0) { /*
perror("bind oldroot failed"); * Recreate dns resolver iif configured by pod spec. Other cases
goto fail; * are handled by hyperd instead.
} */
/* reuse oldroot array */ setup_dns = arg->pod->dns != NULL && arg->pod->d_num > 0;
sprintf(oldroot, "%s/%s/", root, container->rootfs); if (container_setup_init_layer(container, setup_dns) < 0) {
/* pivot_root won't work, see fprintf(stderr, "container sets up init layer failed\n");
* Documention/filesystem/ramfs-rootfs-initramfs.txt */
chroot(oldroot);
chdir("/");
if (container_setup_volume(container) < 0) {
fprintf(stderr, "container sets up voulme failed\n");
goto fail; goto fail;
} }
@@ -427,8 +592,11 @@ static int hyper_container_init(void *data)
goto fail; goto fail;
} }
if (container_setup_sysctl(container) < 0) { // ignore error of setup modules
fprintf(stderr, "container sets up sysctl failed\n"); container_setup_modules(container);
if (container_setup_volume(container) < 0) {
fprintf(stderr, "container sets up voulme failed\n");
goto fail; goto fail;
} }
@@ -437,33 +605,40 @@ static int hyper_container_init(void *data)
goto fail; goto fail;
} }
// manipulate the rootfs of the container/namespace: move the prepared path @rootfs to /
if (mount(rootfs, "/", NULL, MS_MOVE, NULL) < 0) {
perror("failed to move rootfs");
goto fail;
}
/* pivot_root won't work, see
* Documention/filesystem/ramfs-rootfs-initramfs.txt */
chroot(".");
chdir("/");
if (container_setup_sysctl(container) < 0) {
fprintf(stderr, "container sets up sysctl failed\n");
goto fail;
}
if (container_setup_workdir(container) < 0) { if (container_setup_workdir(container) < 0) {
fprintf(stderr, "container sets up work directory failed\n"); fprintf(stderr, "container sets up work directory failed\n");
goto fail; goto fail;
} }
container_unmount_oldroot("/.oldroot"); /* wait for ns-opened ready message */
if (hyper_get_type(arg->pipens[0], &type) < 0 || type != READY) {
fflush(stdout); fprintf(stderr, "wait for /proc/self/ns/mnt opened failed\n");
if (container_setup_tty(arg->pipe[1], container) < 0) {
fprintf(stdout, "setup tty failed\n");
goto fail; goto fail;
} }
symlink("/proc/self/fd", "/dev/fd"); hyper_send_type(arg->pipe[1], READY);
symlink("/proc/self/fd/0", "/dev/stdin"); fflush(NULL);
symlink("/proc/self/fd/1", "/dev/stdout"); _exit(0);
symlink("/proc/self/fd/2", "/dev/stderr");
execvp(container->exec.argv[0], container->exec.argv);
perror("exec container command failed");
_exit(-1);
fail: fail:
hyper_send_type(arg->pipe[1], ERROR); hyper_send_type(arg->pipe[1], ERROR);
_exit(-1); _exit(125);
} }
static int hyper_setup_pty(struct hyper_container *c) static int hyper_setup_pty(struct hyper_container *c)
@@ -472,7 +647,7 @@ static int hyper_setup_pty(struct hyper_container *c)
sprintf(root, "/tmp/hyper/%s/devpts/", c->id); sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
if (hyper_mkdir(root) < 0) { if (hyper_mkdir(root, 0755) < 0) {
perror("make container pts directroy failed"); perror("make container pts directroy failed");
return -1; return -1;
} }
@@ -483,33 +658,31 @@ static int hyper_setup_pty(struct hyper_container *c)
return -1; return -1;
} }
if (hyper_setup_exec_tty(&c->exec) < 0) {
fprintf(stderr, "setup container pts failed\n");
return -1;
}
return 0; return 0;
} }
int hyper_start_container(struct hyper_container *container, int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod)
int utsns, int ipcns, struct hyper_pod *pod)
{ {
int stacksize = getpagesize() * 4; int stacksize = getpagesize() * 42;
struct hyper_container_arg arg = { struct hyper_container_arg arg = {
.c = container, .c = container,
.utsns = utsns, .pod = pod,
.ipcns = ipcns,
.pipe = {-1, -1}, .pipe = {-1, -1},
.pipens = {-1, -1},
}; };
int flags = CLONE_NEWNS | SIGCHLD; int flags = CLONE_NEWNS | SIGCHLD;
char path[128]; char path[128];
uint32_t type;
void *stack; void *stack;
uint32_t type;
int pid; int pid;
if (container->image == NULL || container->exec.argv == NULL) { if (pipe2(arg.pipe, O_CLOEXEC) < 0 || pipe2(arg.pipens, O_CLOEXEC) < 0) {
fprintf(stdout, "container root image %s, argv %p\n", perror("create pipe between pod init execcmd failed");
container->image, container->exec.argv); goto fail;
}
if (hyper_setup_container_portmapping(container, pod) < 0) {
perror("fail to setup port mapping for container");
goto fail; goto fail;
} }
@@ -518,66 +691,49 @@ int hyper_start_container(struct hyper_container *container,
goto fail; goto fail;
} }
if (pipe2(arg.pipe, O_CLOEXEC) < 0) {
perror("create pipe between pod init execcmd failed");
goto fail;
}
if (hyper_watch_exec_pty(&container->exec, pod) < 0) {
fprintf(stderr, "faile to watch container pty\n");
goto fail;
}
stack = malloc(stacksize); stack = malloc(stacksize);
if (stack == NULL) { if (stack == NULL) {
perror("fail to allocate stack for container init"); perror("fail to allocate stack for container init");
goto fail; goto fail;
} }
pid = clone(hyper_container_init, stack + stacksize, flags, &arg); pid = clone(hyper_setup_container_rootfs, stack + stacksize, flags, &arg);
free(stack); free(stack);
if (pid < 0) { if (pid < 0) {
perror("create child process failed"); perror("create child process failed");
goto fail; goto fail;
} }
sprintf(path, "/proc/%d/ns/mnt", pid);
sprintf(path, "/proc/%d/ns/mnt", pid);
container->ns = open(path, O_RDONLY | O_CLOEXEC); container->ns = open(path, O_RDONLY | O_CLOEXEC);
if (container->ns < 0) { if (container->ns < 0) {
perror("open container mount ns failed"); perror("open container mount ns failed");
goto fail; goto fail;
} }
hyper_send_type(arg.pipens[1], READY);
/* wait for ready message */ /* wait for ready message */
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) { if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
fprintf(stderr, "wait for container started failed\n"); fprintf(stderr, "wait for setup container rootfs failed\n");
goto fail; goto fail;
} }
container->exec.pid = pid;
list_add_tail(&container->exec.list, &pod->exec_head);
container->exec.ref++;
close(arg.pipe[0]); close(arg.pipe[0]);
close(arg.pipe[1]); close(arg.pipe[1]);
close(arg.pipens[0]);
fprintf(stdout, "container %s,init pid %d,ref %d\n", container->id, pid, container->exec.ref); close(arg.pipens[1]);
return 0; return 0;
fail: fail:
close(container->ns);
container->ns = -1;
close(arg.pipe[0]); close(arg.pipe[0]);
close(arg.pipe[1]); close(arg.pipe[1]);
close(container->ns); close(arg.pipens[0]);
hyper_reset_event(&container->exec.e); close(arg.pipens[1]);
hyper_reset_event(&container->exec.errev);
container->ns = -1;
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
container->exec.code = -1;
container->exec.seq = 0;
container->exec.ref = 0;
return -1; return -1;
} }
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id) struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id)
{ {
struct hyper_container *c; struct hyper_container *c;
@@ -594,7 +750,7 @@ struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id)
return NULL; return NULL;
} }
void hyper_cleanup_container(struct hyper_container *c) void hyper_cleanup_container(struct hyper_container *c, struct hyper_pod *pod)
{ {
char root[512]; char root[512];
@@ -603,6 +759,7 @@ void hyper_cleanup_container(struct hyper_container *c)
perror("umount devpts failed"); perror("umount devpts failed");
close(c->ns); close(c->ns);
hyper_cleanup_container_portmapping(c, pod);
hyper_free_container(c); hyper_free_container(c);
} }
@@ -611,7 +768,7 @@ void hyper_cleanup_containers(struct hyper_pod *pod)
struct hyper_container *c, *n; struct hyper_container *c, *n;
list_for_each_entry_safe(c, n, &pod->containers, list) list_for_each_entry_safe(c, n, &pod->containers, list)
hyper_cleanup_container(c); hyper_cleanup_container(c, pod);
pod->remains = 0; pod->remains = 0;
} }
+20 -16
View File
@@ -3,23 +3,20 @@
#include "exec.h" #include "exec.h"
struct env {
char *env;
char *value;
};
struct volume { struct volume {
char *device; char *device;
char *scsiaddr; char *scsiaddr;
char *mountpoint; char *mountpoint;
char *fstype; char *fstype;
int readonly; int readonly;
int docker;
}; };
struct fsmap { struct fsmap {
char *source; char *source;
char *path; char *path;
int readonly; int readonly;
int docker;
}; };
struct sysctl { struct sysctl {
@@ -27,33 +24,40 @@ struct sysctl {
char *value; char *value;
}; };
struct port {
int host_port;
int container_port;
char *protocol;
};
struct hyper_container { struct hyper_container {
struct list_head list;
struct hyper_exec exec;
int ns;
uint32_t code;
// configs
char *id; char *id;
char *rootfs; char *rootfs;
char *image; char *image;
char *scsiaddr; char *scsiaddr;
char *workdir;
char *fstype; char *fstype;
struct volume *vols; struct volume *vols;
struct env *envs;
struct fsmap *maps; struct fsmap *maps;
struct sysctl *sys; struct sysctl *sys;
struct port *ports;
int vols_num; int vols_num;
int envs_num;
int maps_num; int maps_num;
int sys_num; int sys_num;
int ns; int ports_num;
uint32_t code; int initialize;
struct list_head list;
struct hyper_exec exec;
}; };
struct hyper_pod; struct hyper_pod;
int hyper_start_container(struct hyper_container *container, int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod);
int utsns, int ipcns, struct hyper_pod *pod); struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id);
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id); void hyper_cleanup_container(struct hyper_container *container, struct hyper_pod *pod);
void hyper_cleanup_container(struct hyper_container *container);
void hyper_cleanup_containers(struct hyper_pod *pod); void hyper_cleanup_containers(struct hyper_pod *pod);
void hyper_free_container(struct hyper_container *c); void hyper_free_container(struct hyper_container *c);
+84 -60
View File
@@ -10,25 +10,25 @@
#include "hyper.h" #include "hyper.h"
#include "event.h" #include "event.h"
void hyper_reset_event(struct hyper_event *de) void hyper_reset_event(struct hyper_event *he)
{ {
free(de->rbuf.data); free(he->rbuf.data);
free(de->wbuf.data); free(he->wbuf.data);
close(de->fd); close(he->fd);
memset(de, 0, sizeof(*de)); memset(he, 0, sizeof(*he));
de->fd = -1; he->fd = -1;
} }
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, void *arg) int hyper_init_event(struct hyper_event *he, struct hyper_event_ops *ops, void *arg)
{ {
struct hyper_buf *rbuf = &de->rbuf; struct hyper_buf *rbuf = &he->rbuf;
struct hyper_buf *wbuf = &de->wbuf; struct hyper_buf *wbuf = &he->wbuf;
memset(rbuf, 0, sizeof(*rbuf)); memset(rbuf, 0, sizeof(*rbuf));
memset(wbuf, 0, sizeof(*wbuf)); memset(wbuf, 0, sizeof(*wbuf));
de->ops = ops; he->ops = ops;
de->ptr = arg; he->ptr = arg;
rbuf->size = ops->rbuf_size; rbuf->size = ops->rbuf_size;
wbuf->size = ops->wbuf_size; wbuf->size = ops->wbuf_size;
@@ -51,22 +51,22 @@ int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, void *
return 0; return 0;
} }
int hyper_add_event(int efd, struct hyper_event *de, int flag) int hyper_add_event(int efd, struct hyper_event *he, int flag)
{ {
struct epoll_event event = { struct epoll_event event = {
.events = flag, .events = flag,
.data.ptr = de, .data.ptr = he,
}; };
de->flag = flag; he->flag = flag;
if (hyper_setfd_nonblock(de->fd) < 0) { if (hyper_setfd_nonblock(he->fd) < 0) {
perror("set fd nonblock failed"); perror("set fd nonblock failed");
return -1; return -1;
} }
fprintf(stdout, "%s add event fd %d, %p\n", __func__, de->fd, de->ops); fprintf(stdout, "%s add event fd %d, %p\n", __func__, he->fd, he->ops);
if (epoll_ctl(efd, EPOLL_CTL_ADD, de->fd, &event) < 0) { if (epoll_ctl(efd, EPOLL_CTL_ADD, he->fd, &event) < 0) {
perror("epoll_ctl fd failed"); perror("epoll_ctl fd failed");
return -1; return -1;
} }
@@ -74,21 +74,21 @@ int hyper_add_event(int efd, struct hyper_event *de, int flag)
return 0; return 0;
} }
int hyper_modify_event(int efd, struct hyper_event *de, int flag) int hyper_modify_event(int efd, struct hyper_event *he, int flag)
{ {
struct epoll_event event = { struct epoll_event event = {
.events = flag, .events = flag,
.data.ptr = de, .data.ptr = he,
}; };
if (de->flag == flag) if (he->flag == flag)
return 0; return 0;
de->flag = flag; he->flag = flag;
fprintf(stdout, "%s modify event fd %d, %p, event %d\n", fprintf(stdout, "%s modify event fd %d, %p, event %d\n",
__func__, de->fd, de, flag); __func__, he->fd, he, flag);
if (epoll_ctl(efd, EPOLL_CTL_MOD, de->fd, &event) < 0) { if (epoll_ctl(efd, EPOLL_CTL_MOD, he->fd, &event) < 0) {
perror("epoll_ctl fd failed"); perror("epoll_ctl fd failed");
return -1; return -1;
} }
@@ -96,39 +96,59 @@ int hyper_modify_event(int efd, struct hyper_event *de, int flag)
return 0; return 0;
} }
static int hyper_getmsg_len(struct hyper_event *de, uint32_t *len) int hyper_requeue_event(int efd, struct hyper_event *ev)
{ {
struct hyper_buf *buf = &de->rbuf; struct epoll_event event = {
.events = ev->flag,
.data.ptr = ev,
};
if (buf->get < de->ops->len_offset + 4) if (epoll_ctl(efd, EPOLL_CTL_DEL, ev->fd, NULL) < 0) {
perror("epoll_ctl del fd failed");
return -1; return -1;
}
if (epoll_ctl(efd, EPOLL_CTL_ADD, ev->fd, &event) < 0) {
perror("epoll_ctl add fd failed");
return -1;
}
*len = hyper_get_be32(buf->data + de->ops->len_offset);
return 0; return 0;
} }
int hyper_event_read(struct hyper_event *de) static int hyper_getmsg_len(struct hyper_event *he, uint32_t *len)
{ {
struct hyper_buf *buf = &de->rbuf; struct hyper_buf *buf = &he->rbuf;
if (buf->get < he->ops->len_offset + 4)
return -1;
*len = hyper_get_be32(buf->data + he->ops->len_offset);
return 0;
}
int hyper_event_read(struct hyper_event *he, int efd)
{
struct hyper_buf *buf = &he->rbuf;
uint32_t len = 4; uint32_t len = 4;
uint8_t data[4]; uint8_t data[4];
int offset = de->ops->len_offset; int offset = he->ops->len_offset;
int end = offset + 4; int end = offset + 4;
int size; int size;
fprintf(stdout, "%s\n", __func__); fprintf(stdout, "%s\n", __func__);
while (hyper_getmsg_len(de, &len) < 0) { while (hyper_getmsg_len(he, &len) < 0) {
size = read(de->fd, buf->data + buf->get, end - buf->get); size = read(he->fd, buf->data + buf->get, end - buf->get);
if (size > 0) { if (size > 0) {
buf->get += size; buf->get += size;
fprintf(stdout, "already read %" PRIu32 " bytes data\n", fprintf(stdout, "already read %" PRIu32 " bytes data\n",
buf->get); buf->get);
if (de->ops->ack) { if (he->ops->ack) {
/* control channel, need ack */ /* control channel, need ack */
hyper_set_be32(data, size); hyper_set_be32(data, size);
hyper_send_msg(de->fd, NEXT, 4, data); hyper_send_msg(he->fd, NEXT, 4, data);
} }
continue; continue;
} }
@@ -151,15 +171,15 @@ int hyper_event_read(struct hyper_event *de)
} }
while (buf->get < len) { while (buf->get < len) {
size = read(de->fd, buf->data + buf->get, len - buf->get); size = read(he->fd, buf->data + buf->get, len - buf->get);
if (size > 0) { if (size > 0) {
buf->get += size; buf->get += size;
fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n", fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n",
size, buf->get); size, buf->get);
if (de->ops->ack) { if (he->ops->ack) {
/* control channel, need ack */ /* control channel, need ack */
hyper_set_be32(data, size); hyper_set_be32(data, size);
hyper_send_msg(de->fd, NEXT, 4, data); hyper_send_msg(he->fd, NEXT, 4, data);
} }
continue; continue;
@@ -178,7 +198,7 @@ int hyper_event_read(struct hyper_event *de)
} }
/* get the whole data */ /* get the whole data */
if (de->ops->handle(de, len) != 0) if (he->ops->handle(he, len) != 0)
return -1; return -1;
/* len: length of the already get new data */ /* len: length of the already get new data */
@@ -188,14 +208,14 @@ int hyper_event_read(struct hyper_event *de)
return 0; return 0;
} }
int hyper_event_write(struct hyper_event *de) int hyper_event_write(struct hyper_event *he, int efd)
{ {
struct hyper_buf *buf = &de->wbuf; struct hyper_buf *buf = &he->wbuf;
uint32_t len = 0; uint32_t len = 0;
int size = 0; int size = 0;
while (len < buf->get) { while (len < buf->get) {
size = write(de->fd, buf->data + len, buf->get - len); size = write(he->fd, buf->data + len, buf->get - len);
if (size <= 0) { if (size <= 0) {
if (errno == EINTR) if (errno == EINTR)
continue; continue;
@@ -210,49 +230,53 @@ int hyper_event_write(struct hyper_event *de)
memmove(buf->data, buf->data + len, buf->get); memmove(buf->data, buf->data + len, buf->get);
if (buf->get == 0) { if (buf->get == 0) {
hyper_modify_event(ctl.efd, de, EPOLLIN); hyper_modify_event(ctl.efd, he, he->flag & ~(EPOLLOUT| EPOLLPRI));
} else if (!FULL(buf)) {
hyper_modify_event(ctl.efd, he, he->flag & ~EPOLLPRI);
} }
return 0; return 0;
} }
void hyper_event_hup(struct hyper_event *de, int efd) void hyper_event_hup(struct hyper_event *he, int efd)
{ {
if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0) if (epoll_ctl(efd, EPOLL_CTL_DEL, he->fd, NULL) < 0)
perror("epoll_ctl del epoll event failed"); perror("epoll_ctl del epoll event failed");
hyper_reset_event(de); hyper_reset_event(he);
} }
int hyper_handle_event(int efd, struct epoll_event *event) int hyper_handle_event(int efd, struct epoll_event *event)
{ {
struct hyper_event *de = event->data.ptr; struct hyper_event *he = event->data.ptr;
fprintf(stdout, "%s get event %d, de %p, fd %d. ops %p\n", fprintf(stdout, "%s get event %d, he %p, fd %d. ops %p\n",
__func__, event->events, de, de->fd, de->ops); __func__, event->events, he, he->fd, he->ops);
/* do not handle hup event if have in event */ /* do not handle hup event if have in event */
if (event->events & EPOLLIN) { if ((event->events & EPOLLIN) && he->ops->read) {
fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n", fprintf(stdout, "%s event EPOLLIN, he %p, fd %d, %p\n",
__func__, de, de->fd, de->ops); __func__, he, he->fd, he->ops);
if (de->ops->read(de) < 0) if (he->ops->read && he->ops->read(he, efd) < 0)
return -1; return -1;
} else if (event->events & EPOLLHUP) { } else if (event->events & EPOLLHUP) {
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n", fprintf(stdout, "%s event EPOLLHUP, he %p, fd %d, %p\n",
__func__, de, de->fd, de->ops); __func__, he, he->fd, he->ops);
if (de->ops->hup) if (he->ops->hup)
de->ops->hup(de, efd); he->ops->hup(he, efd);
return 0; return 0;
} }
if (event->events & EPOLLOUT) { if (event->events & EPOLLOUT) {
fprintf(stdout, "%s event EPOLLOUT, de %p, fd %d, %p\n", fprintf(stdout, "%s event EPOLLOUT, he %p, fd %d, %p\n",
__func__, de, de->fd, de->ops); __func__, he, he->fd, he->ops);
if (de->ops->write && de->ops->write(de) < 0) if (he->ops->write && he->ops->write(he, efd) < 0)
return -1; return -1;
} }
if (event->events & EPOLLERR) { if (event->events & EPOLLERR) {
fprintf(stderr, "get epoll err of not epool in event\n"); fprintf(stderr, "get epoll err of not epool in event\n");
return -1; if (he->ops->hup)
he->ops->hup(he, efd);
return 0;
} }
return 0; return 0;
+8 -4
View File
@@ -7,8 +7,8 @@
struct hyper_event; struct hyper_event;
struct hyper_event_ops { struct hyper_event_ops {
int (*read)(struct hyper_event *e); int (*read)(struct hyper_event *e, int efd);
int (*write)(struct hyper_event *e); int (*write)(struct hyper_event *e, int efd);
int (*handle)(struct hyper_event *e, uint32_t len); int (*handle)(struct hyper_event *e, uint32_t len);
void (*hup)(struct hyper_event *e, int efd); void (*hup)(struct hyper_event *e, int efd);
int rbuf_size; int rbuf_size;
@@ -32,13 +32,17 @@ struct hyper_event {
void *ptr; void *ptr;
}; };
#define FULL(buf) \
(buf->size - buf->get <= 12)
int hyper_add_event(int efd, struct hyper_event *de, int flag); int hyper_add_event(int efd, struct hyper_event *de, int flag);
int hyper_modify_event(int efd, struct hyper_event *de, int flag); int hyper_modify_event(int efd, struct hyper_event *de, int flag);
int hyper_requeue_event(int efd, struct hyper_event *ev);
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops,
void *arg); void *arg);
int hyper_handle_event(int efd, struct epoll_event *event); int hyper_handle_event(int efd, struct epoll_event *event);
void hyper_reset_event(struct hyper_event *de); void hyper_reset_event(struct hyper_event *de);
void hyper_event_hup(struct hyper_event *de, int efd); void hyper_event_hup(struct hyper_event *de, int efd);
int hyper_event_read(struct hyper_event *de); int hyper_event_read(struct hyper_event *dei, int efd);
int hyper_event_write(struct hyper_event *de); int hyper_event_write(struct hyper_event *de, int efd);
#endif #endif
+475 -264
View File
File diff suppressed because it is too large Load Diff
+28 -14
View File
@@ -4,37 +4,51 @@
#include "list.h" #include "list.h"
#include "event.h" #include "event.h"
struct env {
char *env;
char *value;
};
struct hyper_exec { struct hyper_exec {
struct list_head list; struct list_head list;
struct hyper_event e; struct hyper_event stdinev;
struct hyper_event errev; struct hyper_event stdoutev;
char *id; struct hyper_event stderrev;
char **argv;
int argc;
uint64_t seq;
uint64_t errseq;
int pid; int pid;
int ptyno; int ptyno;
int init; int init;
int ptyfd; int ptyfd;
int errfd; int stdinfd;
int stdoutfd;
int stderrfd;
uint8_t close_stdin_request;
uint8_t code; uint8_t code;
uint8_t exit; uint8_t exit;
uint8_t ref; uint8_t ref;
// configs
char *id;
char *user;
char *group;
char **additional_groups;
int nr_additional_groups;
struct env *envs;
int envs_num;
char **argv;
int argc;
int tty; // use tty or not
uint64_t seq;
uint64_t errseq;
char *workdir;
}; };
struct hyper_pod; struct hyper_pod;
int hyper_exec_cmd(char *json, int length); int hyper_exec_cmd(char *json, int length);
int hyper_release_exec(struct hyper_exec *, struct hyper_pod *); int hyper_run_process(struct hyper_exec *e);
int hyper_container_execcmd(struct hyper_pod *pod);
int hyper_setup_exec_tty(struct hyper_exec *e);
int hyper_dup_exec_tty(int fd, struct hyper_exec *e);
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid); struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq); struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code); int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code);
int hyper_watch_exec_pty(struct hyper_exec *exec, struct hyper_pod *pod);
void hyper_cleanup_exec(struct hyper_pod *pod); void hyper_cleanup_exec(struct hyper_pod *pod);
extern struct hyper_event_ops pts_ops;
#endif #endif
+39 -14
View File
@@ -2,12 +2,17 @@
#define _HYPER_H_ #define _HYPER_H_
#include <stdint.h> #include <stdint.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include "net.h" #include "net.h"
#include "list.h" #include "list.h"
#include "exec.h" #include "exec.h"
#include "event.h" #include "event.h"
#include "container.h" #include "container.h"
#include "portmapping.h"
enum { enum {
RESERVED, RESERVED,
@@ -29,6 +34,10 @@ enum {
READFILE, READFILE,
NEWCONTAINER, NEWCONTAINER,
KILLCONTAINER, KILLCONTAINER,
ONLINECPUMEM,
SETUPINTERFACE,
SETUPROUTE,
REMOVECONTAINER,
}; };
enum { enum {
@@ -38,9 +47,9 @@ enum {
}; };
struct hyper_pod { struct hyper_pod {
struct hyper_container *c;
struct hyper_interface *iface; struct hyper_interface *iface;
struct hyper_route *rt; struct hyper_route *rt;
struct portmapping_white_list *portmap_white_lists;
char **dns; char **dns;
struct list_head containers; struct list_head containers;
struct list_head exec_head; struct list_head exec_head;
@@ -49,28 +58,27 @@ struct hyper_pod {
int init_pid; int init_pid;
uint32_t i_num; uint32_t i_num;
uint32_t r_num; uint32_t r_num;
uint32_t e_num;
uint32_t d_num; uint32_t d_num;
uint32_t type; uint32_t type;
/* how many containers are running */ /* how many containers are running */
uint32_t remains; uint32_t remains;
uint8_t policy; uint8_t policy;
int efd; int efd;
struct hyper_event sig; };
struct portmapping_white_list {
char **internal_networks;
char **external_networks;
uint32_t i_num;
uint32_t e_num;
}; };
struct hyper_win_size { struct hyper_win_size {
char *tty;
int row; int row;
int column; int column;
uint64_t seq; uint64_t seq;
}; };
struct hyper_killer {
char *id;
int signal;
};
struct hyper_reader { struct hyper_reader {
char *id; char *id;
char *file; char *file;
@@ -85,18 +93,35 @@ struct hyper_writter {
struct hyper_ctl { struct hyper_ctl {
int efd; int efd;
struct hyper_event sig;
struct hyper_event tty; struct hyper_event tty;
struct hyper_event chan; struct hyper_event chan;
}; };
int hyper_mkdir(char *hyper_path); static inline int hyper_symlink(char *oldpath, char *newpath)
{
return symlink(oldpath, newpath);
}
static inline int hyper_unlink(char *hyper_path)
{
return unlink(hyper_path);
}
static inline int hyper_create(char *hyper_path)
{
int fd = creat(hyper_path, 0755);
if (fd < 0)
return -1;
close(fd);
return 0;
}
int hyper_open_serial(char *tty); int hyper_open_serial(char *tty);
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
int hyper_start_containers(struct hyper_pod *pod);
void hyper_cleanup_pod(struct hyper_pod *pod); void hyper_cleanup_pod(struct hyper_pod *pod);
int hyper_enter_sandbox(struct hyper_pod *pod, int pidpipe);
extern struct hyper_pod global_pod; extern struct hyper_pod global_pod;
extern struct hyper_ctl ctl; extern struct hyper_ctl ctl;
extern struct hyper_exec *global_exec; extern sigset_t orig_mask;
#endif #endif
+260 -317
View File
@@ -6,6 +6,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/resource.h>
#include <fcntl.h> #include <fcntl.h>
#include <dirent.h> #include <dirent.h>
#include <sched.h> #include <sched.h>
@@ -15,7 +16,6 @@
#include <limits.h> #include <limits.h>
#include <mntent.h> #include <mntent.h>
#include <sys/epoll.h> #include <sys/epoll.h>
#include <sys/signalfd.h>
#include <inttypes.h> #include <inttypes.h>
#include <ctype.h> #include <ctype.h>
@@ -33,25 +33,22 @@ struct hyper_pod global_pod = {
.containers = LIST_HEAD_INIT(global_pod.containers), .containers = LIST_HEAD_INIT(global_pod.containers),
.exec_head = LIST_HEAD_INIT(global_pod.exec_head), .exec_head = LIST_HEAD_INIT(global_pod.exec_head),
}; };
struct hyper_exec *global_exec;
#define MAXEVENTS 10 #define MAXEVENTS 10
struct hyper_ctl ctl; struct hyper_ctl ctl;
static struct hyper_event_ops hyper_signal_ops; sigset_t orig_mask;
static int hyper_handle_exit(struct hyper_pod *pod); static int hyper_handle_exit(struct hyper_pod *pod);
static int hyper_stop_pod(struct hyper_pod *pod); static int hyper_stop_pod(struct hyper_pod *pod);
static int hyper_set_win_size(char *json, int length) static int hyper_set_win_size(char *json, int length)
{ {
struct hyper_win_size ws = { struct hyper_win_size ws;
.tty = NULL,
};
struct winsize size; struct winsize size;
struct hyper_exec *exec; struct hyper_exec *exec;
char path[128]; int ret;
int fd, ret;
fprintf(stdout, "call hyper_win_size, json %s, len %d\n", json, length); fprintf(stdout, "call hyper_win_size, json %s, len %d\n", json, length);
if (hyper_parse_winsize(&ws, json, length) < 0) { if (hyper_parse_winsize(&ws, json, length) < 0) {
@@ -59,39 +56,19 @@ static int hyper_set_win_size(char *json, int length)
return -1; return -1;
} }
if (!ws.tty) { exec = hyper_find_exec_by_seq(&global_pod, ws.seq);
exec = hyper_find_exec_by_seq(&global_pod, ws.seq); if (exec == NULL) {
if (exec == NULL) { fprintf(stdout, "can not find exec whose seq is %" PRIu64"\n", ws.seq);
fprintf(stdout, "can not find exec whose seq is %" PRIu64"\n", ws.seq); return 0;
return 0;
}
fprintf(stdout, "find exec %s, pid is %d, seq is %" PRIu64"\n",
exec->id ? exec->id : "pod", exec->pid, ws.seq);
fd = dup(exec->ptyfd);
} else {
if (sprintf(path, "/dev/%s", ws.tty) < 0) {
fprintf(stderr, "get tty device failed\n");
return -1;
}
fd = hyper_open_serial_dev(path);
}
if (fd < 0) {
perror("cannot open pty device to set term size");
goto out;
} }
size.ws_row = ws.row; size.ws_row = ws.row;
size.ws_col = ws.column; size.ws_col = ws.column;
ret = ioctl(fd, TIOCSWINSZ, &size); ret = ioctl(exec->ptyfd, TIOCSWINSZ, &size);
if (ret < 0) if (ret < 0)
perror("cannot ioctl to set pty device term size"); perror("cannot ioctl to set pty device term size");
close(fd);
out:
free(ws.tty);
return ret; return ret;
} }
@@ -145,7 +122,7 @@ static void hyper_term_all(struct hyper_pod *pod)
DIR *dp; DIR *dp;
struct dirent *de; struct dirent *de;
pid_t *pids = NULL; pid_t *pids = NULL;
struct hyper_container *c; struct hyper_exec *e;
dp = opendir("/proc"); dp = opendir("/proc");
if (dp == NULL) if (dp == NULL)
@@ -177,8 +154,8 @@ static void hyper_term_all(struct hyper_pod *pod)
free(pids); free(pids);
closedir(dp); closedir(dp);
list_for_each_entry(c, &pod->containers, list) list_for_each_entry(e, &pod->exec_head, list)
hyper_kill_process(c->exec.pid); hyper_kill_process(e->pid);
} }
static int hyper_handle_exit(struct hyper_pod *pod) static int hyper_handle_exit(struct hyper_pod *pod)
@@ -207,79 +184,14 @@ static int hyper_handle_exit(struct hyper_pod *pod)
return 0; return 0;
} }
static int hyper_signal_loop(struct hyper_event *de) static void pod_init_sigchld(int sig)
{ {
int size; hyper_handle_exit(NULL);
struct signalfd_siginfo sinfo;
struct hyper_pod *pod = de->ptr;
fprintf(stdout, "%s write to ctl tty fd\n", __func__);
while (1) {
size = read(de->fd, &sinfo, sizeof(struct signalfd_siginfo));
if (size <= 0) {
if (errno == EINTR)
continue;
if (errno == EAGAIN)
break;
perror("fail to read signal fd");
return -1;
} else if (size != sizeof(struct signalfd_siginfo)) {
perror("read signalfd siginfo failed");
return -1;
}
if (sinfo.ssi_signo != SIGCHLD) {
fprintf(stderr, "why give me signal %d?\n", sinfo.ssi_signo);
return 0;
}
hyper_handle_exit(pod);
}
return 0;
} }
static int pod_init_loop(struct hyper_pod *pod) static void hyper_init_sigchld(int sig)
{ {
int i, n; hyper_handle_exit(&global_pod);
struct epoll_event *events;
pod->efd = epoll_create1(EPOLL_CLOEXEC);
if (pod->efd < 0) {
perror("epoll_create failed");
return -1;
}
fprintf(stdout, "hyper_init_event pod signal event %p, ops %p, fd %d\n",
&pod->sig, &hyper_signal_ops, pod->sig.fd);
if (hyper_init_event(&pod->sig, &hyper_signal_ops, NULL) < 0 ||
hyper_add_event(pod->efd, &pod->sig, EPOLLIN) < 0) {
return -1;
}
events = calloc(MAXEVENTS, sizeof(*events));
while (1) {
n = epoll_wait(pod->efd, events, MAXEVENTS, -1);
fprintf(stdout, "%s epoll_wait %d\n", __func__, n);
if (n < 0) {
if (errno == EINTR)
continue;
perror("pod wait event failed");
return -1;
}
for (i = 0; i < n; i++) {
if (hyper_handle_event(pod->efd, &events[i]) < 0)
return -1;
}
}
close(pod->efd);
return 0;
} }
struct hyper_pod_arg { struct hyper_pod_arg {
@@ -294,26 +206,17 @@ static int hyper_pod_init(void *data)
sigset_t mask; sigset_t mask;
close(arg->ctl_pipe[0]); close(arg->ctl_pipe[0]);
close(ctl.sig.fd);
close(ctl.efd); close(ctl.efd);
close(ctl.chan.fd); close(ctl.chan.fd);
close(ctl.tty.fd); close(ctl.tty.fd);
pod->sig.fd = -1;
sigemptyset(&mask); sigemptyset(&mask);
sigaddset(&mask, SIGCHLD); sigaddset(&mask, SIGCHLD);
if (sigprocmask(SIG_UNBLOCK, &mask, NULL) < 0) {
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
perror("sigprocmask SIGCHLD failed"); perror("sigprocmask SIGCHLD failed");
goto fail; return -1;
}
pod->sig.fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
if (pod->sig.fd < 0) {
perror("create pod signalfd failed");
goto fail;
} }
signal(SIGCHLD, pod_init_sigchld);
/* mount new proc directory */ /* mount new proc directory */
if (umount("/proc") < 0) { if (umount("/proc") < 0) {
@@ -338,148 +241,36 @@ static int hyper_pod_init(void *data)
close(arg->ctl_pipe[1]); close(arg->ctl_pipe[1]);
pod_init_loop(pod); for (;;)
fprintf(stdout, "pod init exit\n"); pause(); /* infinite loop and handle SIGCHLD */
out: out:
_exit(-1); _exit(-1);
fail: fail:
hyper_send_type(arg->ctl_pipe[1], ERROR); hyper_send_type(arg->ctl_pipe[1], ERROR);
close(arg->ctl_pipe[1]); close(arg->ctl_pipe[1]);
close(pod->sig.fd);
goto out; goto out;
} }
struct hyper_stage0_arg { static int hyper_start_containers(struct hyper_pod *pod)
struct hyper_pod *pod;
struct hyper_container *container;
int ctl_pipe[2];
};
// stage0: enter the pidns
static int hyper_container_stage0(void *data)
{
int pidns, ipcns, utsns, ret;
struct hyper_container *c;
struct hyper_stage0_arg *arg;
struct hyper_pod *pod;
char path[64];
arg = data;
pod = arg->pod;
c = arg->container;
ret = pidns = ipcns = utsns = -1;
sprintf(path, "/proc/%d/ns/pid", pod->init_pid);
pidns = open(path, O_RDONLY| O_CLOEXEC);
if (pidns < 0) {
perror("fail to open pidns of pod init");
goto out;
}
/* enter pidns of pod init, so the children of this process will run in
* pidns of pod init, see man 2 setns */
if (setns(pidns, CLONE_NEWPID) < 0) {
perror("enter pidns of pod init failed");
goto out;
}
sprintf(path, "/proc/%d/ns/uts", pod->init_pid);
utsns = open(path, O_RDONLY| O_CLOEXEC);
if (utsns < 0) {
perror("fail to open utsns of pod init");
goto out;
}
sprintf(path, "/proc/%d/ns/ipc", pod->init_pid);
ipcns = open(path, O_RDONLY| O_CLOEXEC);
if (ipcns < 0) {
perror("fail to open ipcns of pod init");
goto out;
}
ret = hyper_start_container(c, utsns, ipcns, pod);
out:
if (hyper_send_type(arg->ctl_pipe[1], ret ? ERROR : READY) < 0) {
fprintf(stderr, "container init send ready message failed\n");
}
close(pidns);
close(utsns);
close(ipcns);
/* hyper_container_stage0 shares fd table with init, let init closes pipe. */
//close(arg->ctl_pipe[0]);
//close(arg->ctl_pipe[1]);
_exit(ret);
}
int hyper_start_container_stage0(struct hyper_container *c, struct hyper_pod *pod)
{
int stacksize = getpagesize() * 4;
void *stack = NULL;
struct hyper_stage0_arg arg = {
.pod = pod,
.container = c,
.ctl_pipe = {-1, -1},
};
int ret = -1, pid;
uint32_t type;
if (pipe2(arg.ctl_pipe, O_CLOEXEC) < 0) {
perror("create pipe between hyper init and pod init failed");
goto out;
}
stack = malloc(stacksize);
if (stack == NULL) {
perror("fail to allocate stack for container init");
goto out;
}
pid = clone(hyper_container_stage0, stack + stacksize, CLONE_VM| CLONE_FILES| SIGCHLD, &arg);
free(stack);
if (pid < 0) {
perror("enter container pid ns failed");
goto out;
}
/* Wait for container start */
if (hyper_get_type(arg.ctl_pipe[0], &type) < 0) {
perror("get enter_container_pidns ready message failed");
goto out;
}
if (type != READY) {
fprintf(stderr, "get incorrect enter_container_pidns message type %d, expect READY\n",
type);
goto out;
}
/* container process is spawned and ready to execute */
pod->remains++;
ret = 0;
out:
close(arg.ctl_pipe[0]);
close(arg.ctl_pipe[1]);
return ret;
}
int hyper_start_containers(struct hyper_pod *pod)
{ {
struct hyper_container *c; struct hyper_container *c;
// TODO: setup containers and run container init processes
// via separated hyperstart APIs
list_for_each_entry(c, &pod->containers, list) { list_for_each_entry(c, &pod->containers, list) {
if (hyper_start_container_stage0(c, pod) < 0) if (hyper_setup_container(c, pod) < 0)
return -1; return -1;
if (hyper_run_process(&c->exec) < 0)
return -1;
pod->remains++;
} }
return 0; return 0;
} }
static int hyper_setup_container(struct hyper_pod *pod) static int hyper_setup_pod_init(struct hyper_pod *pod)
{ {
int stacksize = getpagesize() * 4; int stacksize = getpagesize() * 4;
int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC |
@@ -494,7 +285,7 @@ static int hyper_setup_container(struct hyper_pod *pod)
void *stack; void *stack;
int ret = -1; int ret = -1;
if (hyper_socketpair(PF_UNIX, SOCK_STREAM, 0, arg.ctl_pipe) < 0) { if (pipe2(arg.ctl_pipe, O_CLOEXEC) < 0) {
perror("create pipe between hyper init and pod init failed"); perror("create pipe between hyper init and pod init failed");
goto out; goto out;
} }
@@ -526,11 +317,6 @@ static int hyper_setup_container(struct hyper_pod *pod)
goto out; goto out;
} }
if (hyper_start_containers(pod) < 0) {
fprintf(stderr, "start containers failed\n");
goto out;
}
ret = 0; ret = 0;
out: out:
close(arg.ctl_pipe[1]); close(arg.ctl_pipe[1]);
@@ -541,6 +327,63 @@ out:
return ret; return ret;
} }
// enter the sanbox and pass to the child, shouldn't call from the init process
int hyper_enter_sandbox(struct hyper_pod *pod, int pidpipe)
{
int ret = -1, pidns = -1, utsns = -1, ipcns = -1;
char path[512];
sprintf(path, "/proc/%d/ns/pid", pod->init_pid);
pidns = open(path, O_RDONLY| O_CLOEXEC);
if (pidns < 0) {
perror("fail to open pidns of pod init");
goto out;
}
sprintf(path, "/proc/%d/ns/uts", pod->init_pid);
utsns = open(path, O_RDONLY| O_CLOEXEC);
if (utsns < 0) {
perror("fail to open utsns of pod init");
goto out;
}
sprintf(path, "/proc/%d/ns/ipc", pod->init_pid);
ipcns = open(path, O_RDONLY| O_CLOEXEC);
if (ipcns < 0) {
perror("fail to open ipcns of pod init");
goto out;
}
if (setns(pidns, CLONE_NEWPID) < 0 ||
setns(utsns, CLONE_NEWUTS) < 0 ||
setns(ipcns, CLONE_NEWIPC) < 0) {
perror("fail to enter the sandbox");
goto out;
}
/* current process isn't in the pidns even setns(pidns, CLONE_NEWPID)
* was called. fork() is needed, so that the child process will run in
* the pidns, see man 2 setns */
ret = fork();
if (ret < 0) {
perror("fail to fork");
goto out;
} else if (ret > 0) {
fprintf(stdout, "create child process pid=%d in the sandbox\n", ret);
if (pidpipe > 0) {
hyper_send_type(pidpipe, ret);
}
_exit(0);
}
out:
close(pidns);
close(ipcns);
close(utsns);
return ret;
}
#ifdef WITH_VBOX #ifdef WITH_VBOX
#define MAX_HOST_NAME 256 #define MAX_HOST_NAME 256
@@ -577,7 +420,7 @@ static int hyper_setup_shared(struct hyper_pod *pod)
return 0; return 0;
} }
if (hyper_mkdir("/tmp/hyper/shared") < 0) { if (hyper_mkdir("/tmp/hyper/shared", 0755) < 0) {
perror("fail to create /tmp/hyper/shared"); perror("fail to create /tmp/hyper/shared");
return -1; return -1;
} }
@@ -608,13 +451,13 @@ static int hyper_setup_shared(struct hyper_pod *pod)
return 0; return 0;
} }
if (hyper_mkdir("/tmp/hyper/shared") < 0) { if (hyper_mkdir("/tmp/hyper/shared", 0755) < 0) {
perror("fail to create /tmp/hyper/shared"); perror("fail to create /tmp/hyper/shared");
return -1; return -1;
} }
if (mount(pod->share_tag, "/tmp/hyper/shared", "9p", if (mount(pod->share_tag, "/tmp/hyper/shared", "9p",
MS_MGC_VAL| MS_NODEV, "trans=virtio,cache=loose") < 0) { MS_MGC_VAL| MS_NODEV, "trans=virtio") < 0) {
perror("fail to mount shared dir"); perror("fail to mount shared dir");
return -1; return -1;
@@ -627,7 +470,7 @@ static int hyper_setup_shared(struct hyper_pod *pod)
static int hyper_setup_pod(struct hyper_pod *pod) static int hyper_setup_pod(struct hyper_pod *pod)
{ {
/* create tmp proc directroy */ /* create tmp proc directroy */
if (hyper_mkdir("/tmp/hyper/proc") < 0) { if (hyper_mkdir("/tmp/hyper/proc", 0755) < 0) {
perror("create tmp proc failed"); perror("create tmp proc failed");
return -1; return -1;
} }
@@ -647,7 +490,12 @@ static int hyper_setup_pod(struct hyper_pod *pod)
return -1; return -1;
} }
if (hyper_setup_container(pod) < 0) { if (hyper_setup_portmapping(pod) < 0) {
fprintf(stderr, "setup port mapping failed\n");
return -1;
}
if (hyper_setup_pod_init(pod) < 0) {
fprintf(stderr, "start container failed\n"); fprintf(stderr, "start container failed\n");
return -1; return -1;
} }
@@ -669,11 +517,11 @@ static void hyper_print_uptime(void)
close(fd); close(fd);
} }
static int hyper_destroy_pod(struct hyper_pod *pod) static int hyper_destroy_pod(struct hyper_pod *pod, int error)
{ {
if (pod->init_pid == 0) { if (pod->init_pid == 0) {
/* Pod stopped, just shutdown */ /* Pod stopped, just shutdown */
hyper_shutdown(); hyper_shutdown(error);
} else { } else {
/* Kill pod */ /* Kill pod */
hyper_term_all(pod); hyper_term_all(pod);
@@ -690,13 +538,20 @@ static int hyper_start_pod(char *json, int length)
if (pod->init_pid) if (pod->init_pid)
fprintf(stdout, "pod init_pid exist %d\n", pod->init_pid); fprintf(stdout, "pod init_pid exist %d\n", pod->init_pid);
hyper_sync_time_hctosys();
if (hyper_parse_pod(pod, json, length) < 0) { if (hyper_parse_pod(pod, json, length) < 0) {
fprintf(stderr, "parse pod json failed\n"); fprintf(stderr, "parse pod json failed\n");
return -1; return -1;
} }
if (hyper_setup_pod(pod) < 0) { if (hyper_setup_pod(pod) < 0) {
hyper_destroy_pod(pod); hyper_destroy_pod(pod, 1);
return -1;
}
if (hyper_start_containers(pod) < 0) {
fprintf(stderr, "start containers failed\n");
hyper_destroy_pod(pod, 1);
return -1; return -1;
} }
@@ -723,35 +578,71 @@ static int hyper_new_container(char *json, int length)
} }
list_add_tail(&c->list, &pod->containers); list_add_tail(&c->list, &pod->containers);
ret = hyper_start_container_stage0(c, pod); ret = hyper_setup_container(c, pod);
if (ret >= 0)
ret = hyper_run_process(&c->exec);
if (ret < 0) { if (ret < 0) {
//TODO full grace cleanup //TODO full grace cleanup
hyper_cleanup_container(c); hyper_cleanup_container(c, pod);
} }
pod->remains++;
return ret; return ret;
} }
static int hyper_kill_container(char *json, int length) static int hyper_kill_container(char *json, int length)
{ {
struct hyper_killer killer;
struct hyper_container *c; struct hyper_container *c;
struct hyper_pod *pod = &global_pod; struct hyper_pod *pod = &global_pod;
int ret = -1; int ret = -1;
if (hyper_parse_kill_container(&killer, json, length) < 0) { JSON_Value *value = hyper_json_parse(json, length);
if (value == NULL) {
goto out; goto out;
} }
c = hyper_find_container(pod, killer.id); const char *id = json_object_get_string(json_object(value), "container");
c = hyper_find_container(pod, id);
if (c == NULL) { if (c == NULL) {
fprintf(stderr, "can not find container whose id is %s\n", killer.id); fprintf(stderr, "can not find container whose id is %s\n", id);
goto out; goto out;
} }
kill(c->exec.pid, killer.signal); kill(c->exec.pid, (int)json_object_get_number(json_object(value), "signal"));
ret = 0; ret = 0;
out: out:
json_value_free(value);
return ret;
}
static int hyper_remove_container(char *json, int length)
{
struct hyper_container *c;
struct hyper_pod *pod = &global_pod;
int ret = -1;
JSON_Value *value = hyper_json_parse(json, length);
if (value == NULL) {
goto out;
}
const char *id = json_object_get_string(json_object(value), "container");
c = hyper_find_container(pod, id);
if (c == NULL) {
fprintf(stderr, "can not find container whose id is %s\n", id);
goto out;
}
if (c->exec.exit != 1) {
fprintf(stderr, "container %s has not been stopped\n", id);
goto out;
}
hyper_cleanup_container(c, pod);
ret = 0;
out:
json_value_free(value);
return ret; return ret;
} }
@@ -762,7 +653,6 @@ static int hyper_cmd_write_file(char *json, int length)
struct hyper_pod *pod = &global_pod; struct hyper_pod *pod = &global_pod;
int pipe[2] = {-1, -1}; int pipe[2] = {-1, -1};
int pid, mntns = -1, fd; int pid, mntns = -1, fd;
char path[512];
int len = 0, size, ret = -1; int len = 0, size, ret = -1;
fprintf(stdout, "%s\n", __func__); fprintf(stdout, "%s\n", __func__);
@@ -804,20 +694,14 @@ static int hyper_cmd_write_file(char *json, int length)
goto out; goto out;
} }
/* TODO: wait for container finishing setup root */
if (setns(mntns, CLONE_NEWNS) < 0) { if (setns(mntns, CLONE_NEWNS) < 0) {
perror("fail to enter container ns"); perror("fail to enter container ns");
goto exit; goto exit;
} }
sprintf(path, "/tmp/hyper/%s/root/%s/", c->id, c->rootfs);
fprintf(stdout, "write file %s, data len %d\n", writter.file, writter.len); fprintf(stdout, "write file %s, data len %d\n", writter.file, writter.len);
/* TODO: wait for container finishing setup root */
if (chroot(path) < 0) {
perror("chroot for exec command failed");
goto exit;
}
fd = open(writter.file, O_CREAT| O_TRUNC| O_WRONLY, 0644); fd = open(writter.file, O_CREAT| O_TRUNC| O_WRONLY, 0644);
if (fd < 0) { if (fd < 0) {
perror("fail to open target file"); perror("fail to open target file");
@@ -866,6 +750,7 @@ static int hyper_do_cmd_read_file(void *data)
int len = 0, size, fd, ret = -1; int len = 0, size, fd, ret = -1;
struct hyper_file_arg *arg = data; struct hyper_file_arg *arg = data;
/* TODO: wait for container finishing setup root */
if (setns(arg->mntns, CLONE_NEWNS) < 0) { if (setns(arg->mntns, CLONE_NEWNS) < 0) {
perror("fail to enter container ns"); perror("fail to enter container ns");
goto err; goto err;
@@ -873,12 +758,6 @@ static int hyper_do_cmd_read_file(void *data)
fprintf(stdout, "read file %s\n", arg->file); fprintf(stdout, "read file %s\n", arg->file);
/* TODO: wait for container finishing setup root */
if (chroot(arg->root) < 0) {
perror("chroot for exec command failed");
goto err;
}
if (stat(arg->file, &st) < 0) { if (stat(arg->file, &st) < 0) {
perror("fail to state file"); perror("fail to state file");
goto err; goto err;
@@ -916,7 +795,7 @@ static int hyper_do_cmd_read_file(void *data)
ret = 0; ret = 0;
err: err:
hyper_send_type(arg->pipe[1], ret ? ERROR : READY); hyper_send_type(arg->pipe[1], ret ? ERROR : READY);
return ret; _exit(ret);
} }
static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_t **data) static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_t **data)
@@ -929,7 +808,7 @@ static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_
}; };
int stacksize = getpagesize() * 4; int stacksize = getpagesize() * 4;
void *stack = NULL; void *stack = NULL;
int pid, ret = -1; int pid, ret = -1, status;
uint32_t type; uint32_t type;
fprintf(stdout, "%s\n", __func__); fprintf(stdout, "%s\n", __func__);
@@ -958,7 +837,6 @@ static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_
arg.file = reader.file; arg.file = reader.file;
arg.datalen = datalen; arg.datalen = datalen;
arg.data = data; arg.data = data;
sprintf(arg.root, "/tmp/hyper/%s/root/%s/", c->id, c->rootfs);
stack = malloc(stacksize); stack = malloc(stacksize);
if (stack == NULL) { if (stack == NULL) {
@@ -966,13 +844,17 @@ static int hyper_cmd_read_file(char *json, int length, uint32_t *datalen, uint8_
goto out; goto out;
} }
pid = clone(hyper_do_cmd_read_file, stack + stacksize, CLONE_VM| SIGCHLD, &arg); pid = clone(hyper_do_cmd_read_file, stack + stacksize, CLONE_VM| SIGQUIT, &arg);
free(stack);
if (pid < 0) { if (pid < 0) {
perror("fail to fork writter process"); perror("fail to fork writter process");
goto out; goto out;
} }
if (waitpid(pid, &status, __WCLONE) <= 0) {
perror("waiting hyper_do_cmd_read_file finish failed");
goto out;
}
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) { if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
fprintf(stderr, "%s to incorrect type %" PRIu32 "\n", __func__, type); fprintf(stderr, "%s to incorrect type %" PRIu32 "\n", __func__, type);
goto out; goto out;
@@ -984,10 +866,23 @@ out:
close(arg.pipe[1]); close(arg.pipe[1]);
free(reader.id); free(reader.id);
free(reader.file); free(reader.file);
free(stack);
return ret; return ret;
} }
static void hyper_cmd_online_cpu_mem()
{
int pid = fork();
if (pid < 0) {
perror("fail to fork online process");
} else if (pid == 0) {
online_cpu();
online_memory();
exit(0);
}
}
static void hyper_cleanup_hostname(struct hyper_pod *pod) static void hyper_cleanup_hostname(struct hyper_pod *pod)
{ {
free(pod->hostname); free(pod->hostname);
@@ -1025,6 +920,7 @@ void hyper_cleanup_pod(struct hyper_pod *pod)
hyper_cleanup_network(pod); hyper_cleanup_network(pod);
hyper_cleanup_shared(pod); hyper_cleanup_shared(pod);
hyper_cleanup_dns(pod); hyper_cleanup_dns(pod);
hyper_cleanup_portmapping(pod);
hyper_cleanup_hostname(pod); hyper_cleanup_hostname(pod);
} }
@@ -1107,12 +1003,12 @@ static int hyper_ttyfd_handle(struct hyper_event *de, uint32_t len)
dprintf(stdout, "find exec %s pid %d, seq is %" PRIu64 "\n", dprintf(stdout, "find exec %s pid %d, seq is %" PRIu64 "\n",
exec->id ? exec->id : "pod", exec->pid, exec->seq); exec->id ? exec->id : "pod", exec->pid, exec->seq);
// if exec is exited, the event fd of exec is invalid. don't accept any input. // if exec is exited, the event fd of exec is invalid. don't accept any input.
if (exec->exit) { if (exec->exit || exec->close_stdin_request) {
fprintf(stdout, "exec seq %" PRIu64 " exited, don't accept any input\n", exec->seq); fprintf(stdout, "exec seq %" PRIu64 " exited, don't accept any input\n", exec->seq);
return 0; return 0;
} }
wbuf = &exec->e.wbuf; wbuf = &exec->stdinev.wbuf;
size = wbuf->size - wbuf->get; size = wbuf->size - wbuf->get;
if (size == 0) if (size == 0)
@@ -1123,10 +1019,20 @@ static int hyper_ttyfd_handle(struct hyper_event *de, uint32_t len)
if (size > (len - 12)) if (size > (len - 12))
size = (len - 12); size = (len - 12);
/* size == 0 means we had received eof */
if (size == 0 && !exec->tty) {
exec->close_stdin_request = 1;
/* we can't hup the stdinev here, force hup on next write */
if (hyper_modify_event(ctl.efd, &exec->stdinev, EPOLLOUT) < 0) {
fprintf(stderr, "modify exec pts event to in & out failed\n");
return -1;
}
}
if (size > 0) { if (size > 0) {
memcpy(wbuf->data + wbuf->get, rbuf->data + 12, size); memcpy(wbuf->data + wbuf->get, rbuf->data + 12, size);
wbuf->get += size; wbuf->get += size;
if (hyper_modify_event(ctl.efd, &exec->e, EPOLLIN | EPOLLOUT) < 0) { if (hyper_modify_event(ctl.efd, &exec->stdinev, EPOLLOUT) < 0) {
fprintf(stderr, "modify exec pts event to in & out failed\n"); fprintf(stderr, "modify exec pts event to in & out failed\n");
return -1; return -1;
} }
@@ -1163,7 +1069,7 @@ static int hyper_channel_handle(struct hyper_event *de, uint32_t len)
//break; //break;
case DESTROYPOD: case DESTROYPOD:
fprintf(stdout, "get DESTROYPOD message\n"); fprintf(stdout, "get DESTROYPOD message\n");
hyper_destroy_pod(pod); hyper_destroy_pod(pod, 0);
return 0; return 0;
case EXECCMD: case EXECCMD:
ret = hyper_exec_cmd((char *)buf->data + 8, len - 8); ret = hyper_exec_cmd((char *)buf->data + 8, len - 8);
@@ -1189,6 +1095,18 @@ static int hyper_channel_handle(struct hyper_event *de, uint32_t len)
case KILLCONTAINER: case KILLCONTAINER:
ret = hyper_kill_container((char *)buf->data + 8, len - 8); ret = hyper_kill_container((char *)buf->data + 8, len - 8);
break; break;
case REMOVECONTAINER:
ret = hyper_remove_container((char *)buf->data + 8, len - 8);
break;
case ONLINECPUMEM:
hyper_cmd_online_cpu_mem();
break;
case SETUPINTERFACE:
ret = hyper_cmd_setup_interface((char *)buf->data + 8, len - 8);
break;
case SETUPROUTE:
ret = hyper_cmd_setup_route((char *)buf->data + 8, len - 8);
break;
default: default:
ret = -1; ret = -1;
break; break;
@@ -1221,16 +1139,56 @@ static struct hyper_event_ops hyper_ttyfd_ops = {
.len_offset = 8, .len_offset = 8,
}; };
static struct hyper_event_ops hyper_signal_ops = {
.read = hyper_signal_loop,
.hup = hyper_event_hup,
};
static int hyper_loop(void) static int hyper_loop(void)
{ {
int i, n; int i, n;
struct epoll_event *events; struct epoll_event *events;
struct hyper_pod *pod = &global_pod; struct hyper_pod *pod = &global_pod;
sigset_t mask, omask;
struct rlimit limit;
char *filemax = "1000000";
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
/*
* block SIGCHLD in the loop except when in the syscall of
* epoll_pwait(), it ensures that the SIGCHLD handling and
* the events handling are exclusive.
*/
if (sigprocmask(SIG_BLOCK, &mask, &omask) < 0) {
perror("sigprocmask SIGCHLD failed");
return -1;
}
// need original mask to restore sigmask of child processes
orig_mask = omask;
sigdelset(&omask, SIGCHLD);
signal(SIGCHLD, hyper_init_sigchld);
if (hyper_write_file("/proc/sys/fs/file-max", filemax, strlen(filemax)) < 0) {
fprintf(stderr, "sysctl: setup default file-max(%s) failed\n", filemax);
return -1;
}
// setup open file limit
limit.rlim_cur = limit.rlim_max = atoi(filemax);
if (setrlimit(RLIMIT_NOFILE, &limit) < 0) {
perror("set rlimit for NOFILE failed");
return -1;
}
// setup process num limit
limit.rlim_cur = limit.rlim_max = 30604;
if (setrlimit(RLIMIT_NPROC, &limit) < 0) {
perror("set rlimit for NPROC failed");
return -1;
}
// setup pending signal limit, same with NRPROC
if (setrlimit(RLIMIT_SIGPENDING, &limit) < 0) {
perror("set rlimit for SIGPENDING failed");
return -1;
}
ctl.efd = epoll_create1(EPOLL_CLOEXEC); ctl.efd = epoll_create1(EPOLL_CLOEXEC);
if (ctl.efd < 0) { if (ctl.efd < 0) {
@@ -1252,17 +1210,10 @@ static int hyper_loop(void)
return -1; return -1;
} }
fprintf(stdout, "hyper_init_event hyper signal event %p, ops %p, fd %d\n",
&ctl.sig, &hyper_signal_ops, ctl.sig.fd);
if (hyper_init_event(&ctl.sig, &hyper_signal_ops, pod) < 0 ||
hyper_add_event(ctl.efd, &ctl.sig, EPOLLIN) < 0) {
return -1;
}
events = calloc(MAXEVENTS, sizeof(*events)); events = calloc(MAXEVENTS, sizeof(*events));
while (1) { while (1) {
n = epoll_wait(ctl.efd, events, MAXEVENTS, -1); n = epoll_pwait(ctl.efd, events, MAXEVENTS, -1, &omask);
fprintf(stdout, "%s epoll_wait %d\n", __func__, n); fprintf(stdout, "%s epoll_wait %d\n", __func__, n);
if (n < 0) { if (n < 0) {
@@ -1285,11 +1236,11 @@ static int hyper_loop(void)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char *cmdline, *ctl_serial, *tty_serial; char *cmdline, *ctl_serial, *tty_serial;
sigset_t mask;
if (hyper_mkdir("/dev") < 0 || if (hyper_mkdir("/dev", 0755) < 0 ||
hyper_mkdir("/sys") < 0 || hyper_mkdir("/sys", 0755) < 0 ||
hyper_mkdir("/proc") < 0) { hyper_mkdir("/sbin", 0755) < 0 ||
hyper_mkdir("/proc", 0755) < 0) {
perror("create basic directroy failed"); perror("create basic directroy failed");
return -1; return -1;
} }
@@ -1311,7 +1262,7 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
if (hyper_mkdir("/dev/pts") < 0) { if (hyper_mkdir("/dev/pts", 0755) < 0) {
perror("create basic directroy failed"); perror("create basic directroy failed");
return -1; return -1;
} }
@@ -1321,6 +1272,14 @@ int main(int argc, char *argv[])
return -1; return -1;
} }
symlink("/busybox", "/sh");
symlink("/busybox", "/tar");
symlink("/busybox", "/sbin/modprobe");
symlink("/busybox", "/sbin/depmod");
symlink("/iptables", "/sbin/iptables");
symlink("/iptables", "/sbin/iptables-restore");
symlink("/iptables", "/sbin/iptables-save");
cmdline = read_cmdline(); cmdline = read_cmdline();
setsid(); setsid();
@@ -1343,20 +1302,6 @@ int main(int argc, char *argv[])
setenv("PATH", "/bin:/sbin/:/usr/bin/:/usr/sbin/", 1); setenv("PATH", "/bin:/sbin/:/usr/bin/:/usr/sbin/", 1);
sigemptyset(&mask);
sigaddset(&mask, SIGCHLD);
if (sigprocmask(SIG_BLOCK, &mask, NULL) < 0) {
perror("sigprocmask SIGCHLD failed");
return -1;
}
ctl.sig.fd = signalfd(-1, &mask, SFD_NONBLOCK | SFD_CLOEXEC);
if (ctl.sig.fd < 0) {
perror("create signalfd failed");
return -1;
}
ctl.chan.fd = hyper_setup_ctl_channel(ctl_serial); ctl.chan.fd = hyper_setup_ctl_channel(ctl_serial);
if (ctl.chan.fd < 0) { if (ctl.chan.fd < 0) {
fprintf(stderr, "fail to setup hyper control serial port\n"); fprintf(stderr, "fail to setup hyper control serial port\n");
@@ -1375,8 +1320,6 @@ int main(int argc, char *argv[])
out2: out2:
close(ctl.chan.fd); close(ctl.chan.fd);
out1: out1:
close(ctl.sig.fd);
free(cmdline); free(cmdline);
return 0; return 0;
+64
View File
@@ -11,6 +11,7 @@
#include "hyper.h" #include "hyper.h"
#include "util.h" #include "util.h"
#include "parse.h"
#include "../config.h" #include "../config.h"
void hyper_set_be32(uint8_t *buf, uint32_t val) void hyper_set_be32(uint8_t *buf, uint32_t val)
@@ -783,6 +784,69 @@ void hyper_cleanup_network(struct hyper_pod *pod)
netlink_close(&rth); netlink_close(&rth);
} }
int hyper_cmd_setup_interface(char *json, int length)
{
int ret = -1;
struct hyper_interface *iface;
struct rtnl_handle rth;
if (hyper_rescan() < 0)
return -1;
if (netlink_open(&rth) < 0)
return -1;
iface = hyper_parse_setup_interface(json, length);
if (iface == NULL) {
fprintf(stderr, "parse interface failed\n");
goto out;
}
ret = hyper_setup_interface(&rth, iface);
if (ret < 0) {
fprintf(stderr, "link up device %s failed\n", iface->device);
goto out1;
}
ret = 0;
out1:
free(iface->device);
free(iface->ipaddr);
free(iface->mask);
free(iface);
out:
netlink_close(&rth);
return ret;
}
int hyper_cmd_setup_route(char *json, int length) {
struct hyper_route *rts = NULL;
int i, ret = -1;
uint32_t r_num;
struct rtnl_handle rth;
if (netlink_open(&rth) < 0)
return -1;
if (hyper_parse_setup_routes(&rts, &r_num, json, length) < 0) {
fprintf(stderr, "parse route failed\n");
goto out;
}
for (i = 0; i < r_num; i++) {
ret = hyper_setup_route(&rth, &rts[i]);
if (ret < 0) {
fprintf(stderr, "setup route failed\n");
goto out;
}
}
ret = 0;
out:
netlink_close(&rth);
free(rts);
return ret;
}
int hyper_setup_dns(struct hyper_pod *pod) int hyper_setup_dns(struct hyper_pod *pod)
{ {
int i, fd, ret = -1; int i, fd, ret = -1;
+2
View File
@@ -47,6 +47,8 @@ uint32_t hyper_get_be32(uint8_t *buf);
void hyper_set_be64(uint8_t *buf, uint64_t val); void hyper_set_be64(uint8_t *buf, uint64_t val);
uint64_t hyper_get_be64(uint8_t *buf); uint64_t hyper_get_be64(uint8_t *buf);
int hyper_setup_network(struct hyper_pod *pod); int hyper_setup_network(struct hyper_pod *pod);
int hyper_cmd_setup_interface(char *json, int length);
int hyper_cmd_setup_route(char *json, int length);
void hyper_cleanup_network(struct hyper_pod *pod); void hyper_cleanup_network(struct hyper_pod *pod);
int hyper_setup_dns(struct hyper_pod *pod); int hyper_setup_dns(struct hyper_pod *pod);
void hyper_cleanup_dns(struct hyper_pod *pod); void hyper_cleanup_dns(struct hyper_pod *pod);
+677 -250
View File
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -3,16 +3,19 @@
#include "hyper.h" #include "hyper.h"
#include "jsmn.h" #include "jsmn.h"
#include "parson.h"
int hyper_parse_pod(struct hyper_pod *pod, char *json, int length); int hyper_parse_pod(struct hyper_pod *pod, char *json, int length);
struct hyper_exec *hyper_parse_execcmd(char *json, int length); struct hyper_exec *hyper_parse_execcmd(char *json, int length);
char *json_token_str(char *js, jsmntok_t *t); char *json_token_str(char *js, jsmntok_t *t);
int json_token_streq(char *js, jsmntok_t *t, char *s); int json_token_streq(char *js, jsmntok_t *t, char *s);
int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length); int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length);
int hyper_parse_kill_container(struct hyper_killer *killer, char *json, int length);
int hyper_parse_write_file(struct hyper_writter *writter, char *json, int length); int hyper_parse_write_file(struct hyper_writter *writter, char *json, int length);
int hyper_parse_read_file(struct hyper_reader *reader, char *json, int length); int hyper_parse_read_file(struct hyper_reader *reader, char *json, int length);
struct hyper_container *hyper_parse_new_container(struct hyper_pod *pod, char *json, int length); struct hyper_container *hyper_parse_new_container(struct hyper_pod *pod, char *json, int length);
void hyper_free_container(struct hyper_container *c); void hyper_free_container(struct hyper_container *c);
struct hyper_interface *hyper_parse_setup_interface(char *json, int length);
int hyper_parse_setup_routes(struct hyper_route **routes, uint32_t *r_num, char *json, int length);
JSON_Value *hyper_json_parse(char *json, int length);
#endif #endif
+2070
View File
File diff suppressed because it is too large Load Diff
+223
View File
@@ -0,0 +1,223 @@
/*
Parson ( http://kgabis.github.com/parson/ )
Copyright (c) 2012 - 2016 Krzysztof Gabis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef parson_parson_h
#define parson_parson_h
#ifdef __cplusplus
extern "C"
{
#endif
#include <stddef.h> /* size_t */
/* Types and enums */
typedef struct json_object_t JSON_Object;
typedef struct json_array_t JSON_Array;
typedef struct json_value_t JSON_Value;
enum json_value_type {
JSONError = -1,
JSONNull = 1,
JSONString = 2,
JSONNumber = 3,
JSONObject = 4,
JSONArray = 5,
JSONBoolean = 6
};
typedef int JSON_Value_Type;
enum json_result_t {
JSONSuccess = 0,
JSONFailure = -1
};
typedef int JSON_Status;
typedef void * (*JSON_Malloc_Function)(size_t);
typedef void (*JSON_Free_Function)(void *);
/* Call only once, before calling any other function from parson API. If not called, malloc and free
from stdlib will be used for all allocations */
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
/* Parses first JSON value in a file, returns NULL in case of error */
JSON_Value * json_parse_file(const char *filename);
/* Parses first JSON value in a file and ignores comments (/ * * / and //),
returns NULL in case of error */
JSON_Value * json_parse_file_with_comments(const char *filename);
/* Parses first JSON value in a string, returns NULL in case of error */
JSON_Value * json_parse_string(const char *string);
/* Parses first JSON value in a string and ignores comments (/ * * / and //),
returns NULL in case of error */
JSON_Value * json_parse_string_with_comments(const char *string);
/* Serialization */
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
char * json_serialize_to_string(const JSON_Value *value);
/* Pretty serialization */
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
char * json_serialize_to_string_pretty(const JSON_Value *value);
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
/* Comparing */
int json_value_equals(const JSON_Value *a, const JSON_Value *b);
/* Validation
This is *NOT* JSON Schema. It validates json by checking if object have identically
named fields with matching types.
For example schema {"name":"", "age":0} will validate
{"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
In case of arrays, only first value in schema is checked against all values in tested array.
Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
null validates values of every type.
*/
JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
/*
* JSON Object
*/
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
const char * json_object_get_string (const JSON_Object *object, const char *name);
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* dotget functions enable addressing values with dot notation in nested objects,
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
Because valid names in JSON can contain dots, some values may be inaccessible
this way. */
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
const char * json_object_dotget_string (const JSON_Object *object, const char *name);
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
/* Functions to get available names */
size_t json_object_get_count (const JSON_Object *object);
const char * json_object_get_name (const JSON_Object *object, size_t index);
JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index);
/* Creates new name-value pair or frees and replaces old value with a new one.
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
/* Works like dotget functions, but creates whole hierarchy if necessary.
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
/* Frees and removes name-value pair */
JSON_Status json_object_remove(JSON_Object *object, const char *name);
/* Works like dotget function, but removes name-value pair only on exact match. */
JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
/* Removes all name-value pairs in object */
JSON_Status json_object_clear(JSON_Object *object);
/*
*JSON Array
*/
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
const char * json_array_get_string (const JSON_Array *array, size_t index);
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
size_t json_array_get_count (const JSON_Array *array);
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
* Order of values in array may change during execution. */
JSON_Status json_array_remove(JSON_Array *array, size_t i);
/* Frees and removes from array value at given index and replaces it with given one.
* Does nothing and returns JSONFailure if index doesn't exist.
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
/* Frees and removes all values from array */
JSON_Status json_array_clear(JSON_Array *array);
/* Appends new value at the end of array.
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
JSON_Status json_array_append_number(JSON_Array *array, double number);
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
JSON_Status json_array_append_null(JSON_Array *array);
/*
*JSON Value
*/
JSON_Value * json_value_init_object (void);
JSON_Value * json_value_init_array (void);
JSON_Value * json_value_init_string (const char *string); /* copies passed string */
JSON_Value * json_value_init_number (double number);
JSON_Value * json_value_init_boolean(int boolean);
JSON_Value * json_value_init_null (void);
JSON_Value * json_value_deep_copy (const JSON_Value *value);
void json_value_free (JSON_Value *value);
JSON_Value_Type json_value_get_type (const JSON_Value *value);
JSON_Object * json_value_get_object (const JSON_Value *value);
JSON_Array * json_value_get_array (const JSON_Value *value);
const char * json_value_get_string (const JSON_Value *value);
double json_value_get_number (const JSON_Value *value);
int json_value_get_boolean(const JSON_Value *value);
/* Same as above, but shorter */
JSON_Value_Type json_type (const JSON_Value *value);
JSON_Object * json_object (const JSON_Value *value);
JSON_Array * json_array (const JSON_Value *value);
const char * json_string (const JSON_Value *value);
double json_number (const JSON_Value *value);
int json_boolean(const JSON_Value *value);
#ifdef __cplusplus
}
#endif
#endif
+410
View File
@@ -0,0 +1,410 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <limits.h>
#include <errno.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/utsname.h>
#include <arpa/inet.h>
#include <fcntl.h>
#include "hyper.h"
#include "util.h"
#include "../config.h"
int hyper_init_modules()
{
int status = hyper_cmd("/sbin/depmod");
if (status != 0) {
fprintf(stderr, "depmod failed, status: %d\n", status);
return -1;
}
return 0;
}
int hyper_setup_iptables_rule(struct ipt_rule rule)
{
char check_cmd[512] = {0};
char cmd[512] = {0};
int check = -1;
if (rule.rule != NULL) {
sprintf(check_cmd, "/sbin/iptables -t %s -C %s %s", rule.table, rule.chain, rule.rule);
sprintf(cmd, "/sbin/iptables -t %s %s %s %s", rule.table, rule.op, rule.chain, rule.rule);
} else {
sprintf(cmd, "/sbin/iptables -t %s %s %s", rule.table, rule.op, rule.chain);
}
if (strlen(check_cmd) > 0) {
check = hyper_cmd(check_cmd);
fprintf(stdout, "check iptables '%s', ret: %d\n", check_cmd, check);
}
if (check == 0) {
// iptables rule already exist, do not insert it again
if (!strncmp(rule.op, "-A", strlen("-A")) ||
!strncmp(rule.op, "-I", strlen("-I")) ||
!strncmp(rule.op, "-N", strlen("-N"))) {
fprintf(stdout, "iptables rule '%s' already exist\n", rule.rule);
return 0;
}
}
int status = hyper_cmd(cmd);
fprintf(stdout, "insert iptables '%s', ret: %d\n", cmd, status);
if (status != 0) {
fprintf(stderr, "insert iptables rule failed, ret: %d\n", status);
return -1;
}
return 0;
}
// initialize modules and iptables chains
int hyper_setup_portmapping(struct hyper_pod *pod)
{
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return 0;
}
if (hyper_init_modules() < 0) {
return -1;
}
// iptables -t filter -N hyperstart-INPUT
// iptables -t nat -N hyperstart-PREROUTING
// iptables -t filter -I INPUT -j hyperstart-INPUT
// iptables -t nat -I PREROUTING -j hyperstart-PREROUTING
// iptables -t filter -A hyperstart-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
// iptables -t filter -A hyperstart-INPUT -p icmp -j ACCEPT
// iptables -t filter -A hyperstart-INPUT -i lo -j ACCEPT
// iptables -t filter -A hyperstart-INPUT -j DROP
// iptables -t nat -A hyperstart-PREROUTING -j RETURN
const struct ipt_rule rules[] = {
{
.table = "filter",
.op = "-N",
.chain = "hyperstart-INPUT",
.rule = NULL,
},
{
.table = "nat",
.op = "-N",
.chain = "hyperstart-PREROUTING",
.rule = NULL,
},
{
.table = "filter",
.op = "-I",
.chain = "INPUT",
.rule = "-j hyperstart-INPUT",
},
{
.table = "nat",
.op = "-I",
.chain = "PREROUTING",
.rule = "-j hyperstart-PREROUTING",
},
{
.table = "filter",
.op = "-A",
.chain = "hyperstart-INPUT",
.rule = "-m state --state RELATED,ESTABLISHED -j ACCEPT",
},
{
.table = "filter",
.op = "-A",
.chain = "hyperstart-INPUT",
.rule = "-p icmp -j ACCEPT",
},
{
.table = "filter",
.op = "-A",
.chain = "hyperstart-INPUT",
.rule = "-i lo -j ACCEPT",
},
{
.table = "filter",
.op = "-A",
.chain = "hyperstart-INPUT",
.rule = "-j DROP",
},
{
.table = "nat",
.op = "-A",
.chain = "hyperstart-PREROUTING",
.rule = "-j RETURN",
},
};
int i = 0;
for(i=0; i< sizeof(rules)/sizeof(struct ipt_rule); i++) {
if (hyper_setup_iptables_rule(rules[i])<0) {
return -1;
}
}
return 0;
}
void hyper_cleanup_portmapping(struct hyper_pod *pod)
{
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return;
}
// iptables -t filter -D hyperstart-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
// iptables -t filter -D hyperstart-INPUT -p icmp -j ACCEPT
// iptables -t filter -D hyperstart-INPUT -i lo -j ACCEPT
// iptables -t filter -D hyperstart-INPUT -j DROP
// iptables -t filter -D INPUT -j hyperstart-DNPUT
// iptables -t nat -D hyperstart-PREROUTING -j RETURN
// iptables -t nat -D PREROUTING -j hyperstart-PREROUTING
// iptables -t filter -F hyperstart-INPUT
// iptables -t nat -F hyperstart-PREROUTING
// iptables -t filter -X hyperstart-INPUT
// iptables -t nat -X hyperstart-PREROUTING
const struct ipt_rule rules[] = {
{
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = "-m state --state RELATED,ESTABLISHED -j ACCEPT",
},
{
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = "-p icmp -j ACCEPT",
},
{
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = "-i lo -j ACCEPT",
},
{
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = "-j DROP",
},
{
.table = "nat",
.op = "-D",
.chain = "hyperstart-PREROUTING",
.rule = "-j RETURN",
},
{
.table = "nat",
.op = "-D",
.chain = "PREROUTING",
.rule = "-j hyperstart-PREROUTING",
},
{
.table = "filter",
.op = "-D",
.chain = "INPUT",
.rule = "-j hyperstart-INPUT",
},
{
.table = "nat",
.op = "-F",
.chain = "hyperstart-PREROUTING",
.rule = NULL,
},
{
.table = "nat",
.op = "-X",
.chain = "hyperstart-PREROUTING",
.rule = NULL,
},
{
.table = "filter",
.op = "-F",
.chain = "hyperstart-INPUT",
.rule = NULL,
},
{
.table = "filter",
.op = "-X",
.chain = "hyperstart-INPUT",
.rule = NULL,
},
};
int i = 0;
for(i=0; i< sizeof(rules)/sizeof(struct ipt_rule); i++) {
if (hyper_setup_iptables_rule(rules[i])<0) {
return;
}
}
free(pod->portmap_white_lists->internal_networks);
free(pod->portmap_white_lists->external_networks);
free(pod->portmap_white_lists);
pod->portmap_white_lists = NULL;
}
int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod)
{
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return 0;
}
if (c->ports_num == 0) {
return 0;
}
int i = 0, j = 0;
char rule[128] = {0};
char *network = NULL;
for (i=0; i<c->ports_num; i++) {
// setup port mapping only if host_port is set
if (c->ports[i].host_port > 0) {
for (j=0; j<pod->portmap_white_lists->e_num; j++) {
network = pod->portmap_white_lists->external_networks[j];
// redirect host_port to container_port
if (c->ports[i].host_port != c->ports[i].container_port) {
sprintf(rule, "-s %s -p %s -m %s --dport %d -j REDIRECT --to-ports %d",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].host_port,
c->ports[i].container_port);
struct ipt_rule redirect_rule = {
.table = "nat",
.op = "-I",
.chain = "hyperstart-PREROUTING",
.rule = rule,
};
if (hyper_setup_iptables_rule(redirect_rule)<0) {
fprintf(stderr, "setup redirect_rule '%s' failed\n", rule);
return -1;
}
}
// open container_port to external network
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
struct ipt_rule accept_rule = {
.table = "filter",
.op = "-I",
.chain = "hyperstart-INPUT",
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "setup accept_rule '%s' failed\n", rule);
return -1;
}
}
}
// only allow network request from white list
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
pod->portmap_white_lists->internal_networks[j],
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
struct ipt_rule accept_rule = {
.table = "filter",
.op = "-I",
.chain = "hyperstart-INPUT",
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "setup accept_rule '%s' failed\n", rule);
return -1;
}
}
}
return 0;
}
void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod)
{
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
pod->portmap_white_lists->e_num == 0)) {
return;
}
if (c->ports_num == 0) {
return;
}
int i = 0, j = 0;
char rule[128] = {0};
char *network = NULL;
for (i=0; i<c->ports_num; i++) {
// clean up port mapping only if host_port is set
if (c->ports[i].host_port > 0) {
for (j=0; j<pod->portmap_white_lists->e_num; j++) {
network = pod->portmap_white_lists->external_networks[j];
// delete rules redirecting host_port to container_port
if (c->ports[i].host_port != c->ports[i].container_port) {
sprintf(rule, "-s %s -p %s -m %s --dport %d -j REDIRECT --to-ports %d",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].host_port,
c->ports[i].container_port);
struct ipt_rule redirect_rule = {
.table = "nat",
.op = "-D",
.chain = "hyperstart-PREROUTING",
.rule = rule,
};
if (hyper_setup_iptables_rule(redirect_rule)<0) {
fprintf(stderr, "cleanup redirect '%s' failed\n", rule);
}
}
// open container_port to external network
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
network,
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
struct ipt_rule accept_rule = {
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "cleanup accept_rule '%s' failed\n", rule);
}
}
}
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
pod->portmap_white_lists->internal_networks[j],
c->ports[i].protocol,
c->ports[i].protocol,
c->ports[i].container_port);
struct ipt_rule accept_rule = {
.table = "filter",
.op = "-D",
.chain = "hyperstart-INPUT",
.rule = rule,
};
if (hyper_setup_iptables_rule(accept_rule)<0) {
fprintf(stderr, "cleanup accept_rule '%s' failed\n", rule);
}
}
}
}
+23
View File
@@ -0,0 +1,23 @@
#ifndef _PORT_MAPPING_H_
#define _PORT_MAPPING_H_
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <sys/types.h>
struct ipt_rule {
char *table;
char *op;
char *chain;
char *rule;
};
struct hyper_pod;
struct hyper_container;
int hyper_setup_portmapping(struct hyper_pod *pod);
void hyper_cleanup_portmapping(struct hyper_pod *pod);
int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod);
void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod);
#endif
+317 -32
View File
@@ -9,11 +9,15 @@
#include <errno.h> #include <errno.h>
#include <signal.h> #include <signal.h>
#include <ctype.h> #include <ctype.h>
#include <unistd.h>
#include <mntent.h> #include <mntent.h>
#include <sys/wait.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/reboot.h> #include <sys/reboot.h>
#include <linux/reboot.h> #include <linux/reboot.h>
#include <grp.h>
#include <pwd.h>
#include "util.h" #include "util.h"
#include "hyper.h" #include "hyper.h"
@@ -64,13 +68,34 @@ int hyper_list_dir(char *path)
return 0; return 0;
} }
int hyper_find_sd(char *prefix, char *addr, char **dev) { int hyper_copy_dir(char *src, char *dest)
{
char cmd[512];
snprintf(cmd, sizeof(cmd), "/tar cf - -C %s . | /tar fx - -C %s", src, dest);
return hyper_cmd(cmd);
}
void hyper_sync_time_hctosys() {
int pid;
pid = fork();
if (pid < 0) {
perror("fail to fork to copy directory");
} else if (pid == 0) {
execlp("/busybox", "hwclock", "-s", NULL);
perror("exec hwclock -s command failed");
exit(-1);
}
}
int hyper_find_sd(char *addr, char **dev)
{
struct dirent **list; struct dirent **list;
struct dirent *dir; struct dirent *dir;
char path[512]; char path[512];
int i, num; int i, num;
sprintf(path, "%s/sys/class/scsi_disk/0:0:%s/device/block/", prefix, addr); sprintf(path, "/sys/class/scsi_disk/0:0:%s/device/block/", addr);
fprintf(stdout, "orig dev %s, scan path %s\n", *dev, path); fprintf(stdout, "orig dev %s, scan path %s\n", *dev, path);
num = scandir(path, &list, NULL, NULL); num = scandir(path, &list, NULL, NULL);
@@ -86,7 +111,6 @@ int hyper_find_sd(char *prefix, char *addr, char **dev) {
} }
fprintf(stdout, "%s get %s\n", path, dir->d_name); fprintf(stdout, "%s get %s\n", path, dir->d_name);
free(*dev);
*dev = strdup(dir->d_name); *dev = strdup(dir->d_name);
break; break;
} }
@@ -98,46 +122,290 @@ int hyper_find_sd(char *prefix, char *addr, char **dev) {
return 0; return 0;
} }
int hyper_mkdir(char *hyper_path) static unsigned long id_or_max(const char *name)
{
char *ptr;
long id = strtol(name, &ptr, 10);
if (name == ptr || id < 0 || (errno != 0 && id == 0) || *ptr != '\0')
return ~0UL;
return id;
}
// the same as getpwnam(), but it only parses /etc/passwd and allows name to be id string
struct passwd *hyper_getpwnam(const char *name)
{
uid_t uid = (uid_t)id_or_max(name);
FILE *file = fopen("/etc/passwd", "r");
if (!file) {
perror("faile to open /etc/passwd");
return NULL;
}
for (;;) {
struct passwd *pwd = fgetpwent(file);
if (!pwd)
break;
if (!strcmp(pwd->pw_name, name) || pwd->pw_uid == uid) {
fclose(file);
return pwd;
}
}
fclose(file);
return NULL;
}
// the same as getgrnam(), but it only parses /etc/group and allows the name to be id string
struct group *hyper_getgrnam(const char *name)
{
gid_t gid = (gid_t)id_or_max(name);
FILE *file = fopen("/etc/group", "r");
if (!file) {
perror("faile to open /etc/group");
return NULL;
}
for (;;) {
struct group *gr = fgetgrent(file);
if (!gr)
break;
if (!strcmp(gr->gr_name, name) || gr->gr_gid == gid) {
fclose(file);
return gr;
}
}
fclose(file);
return NULL;
}
// the same as getgrouplist(), but it only parses /etc/group
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
{
int nr = 0, ret;
FILE *file = fopen("/etc/group", "r");
if (!file) {
perror("faile to open /etc/group");
return -1;
}
for (;;) {
struct group *gr = fgetgrent(file);
if (!gr)
break;
int j;
for (j = 0; gr->gr_mem && gr->gr_mem[j]; j++) {
if (!strcmp(gr->gr_mem[j], user)) {
if (nr + 1 < *ngroups)
groups[nr] = gr->gr_gid;
nr++;
}
}
}
fclose(file);
if (nr == 0) {
if (nr + 1 < *ngroups)
groups[nr] = group;
nr++;
}
ret = nr <= *ngroups ? nr : -1;
*ngroups = nr;
return ret;
}
int hyper_write_file(const char *path, const char *value, size_t len)
{
size_t size = 0, l;
int fd = open(path, O_WRONLY);
if (fd < 0) {
perror("open file failed");
return -1;
}
while (size < len) {
l = write(fd, value + size, len - size);
if (l < 0) {
perror("fail to write to file");
close(fd);
return -1;
}
size += l;
}
close(fd);
return 0;
}
/* Trim all trailing '/' of a hyper_path except for the prefix one. */
void hyper_filize(char *hyper_path)
{
char *p;
if (strlen(hyper_path) == 0)
return;
p = &hyper_path[strlen(hyper_path) - 1];
for (; *p == '/' && p != hyper_path; p--) {
*p = '\0';
}
}
static int hyper_create_parent_dir(const char *hyper_path)
{
char *p, *path = strdup(hyper_path);
int ret = 0;
if (path == NULL)
return -1;
p = strrchr(path, '/');
if (p != NULL && p != path) {
*p = '\0';
ret = hyper_mkdir(path, 0777);
}
free(path);
return ret;
}
/* hyper_path must point to a file rather than a directory, e.g., having trailing '/' */
int hyper_create_file(const char *hyper_path)
{
int fd;
struct stat stbuf;
if (stat(hyper_path, &stbuf) >= 0) {
if (S_ISREG(stbuf.st_mode))
return 0;
errno = S_ISDIR(stbuf.st_mode) ? EISDIR : EINVAL;
return -1;
}
if (hyper_create_parent_dir(hyper_path) < 0)
return -1;
fd = open(hyper_path, O_CREAT|O_WRONLY, 0666);
if (fd < 0)
return -1;
close(fd);
fprintf(stdout, "created file %s\n", hyper_path);
return 0;
}
int hyper_mkdir(char *hyper_path, mode_t mode)
{ {
struct stat st; struct stat st;
char *p, *path = strdup(hyper_path); char *p, *path = strdup(hyper_path);
if (path == NULL) { if (path == NULL) {
errno = ENOMEM; errno = ENOMEM;
return -1; goto fail;
} }
fprintf(stdout, "create directory %s\n", path);
if (stat(path, &st) >= 0) { if (stat(path, &st) >= 0) {
if (S_ISDIR(st.st_mode)) if (S_ISDIR(st.st_mode))
return 0; goto out;
errno = ENOTDIR; errno = ENOTDIR;
return -1; goto fail;
} }
if (errno != ENOENT) if (errno != ENOENT)
return -1; goto fail;
p = strrchr(path, '/'); p = strrchr(path, '/');
if (p == NULL) { if (p == NULL) {
errno = EINVAL; errno = EINVAL;
return -1; goto fail;
} }
if (p != path) { if (p != path) {
*p = '\0'; *p = '\0';
if (hyper_mkdir(path) < 0) if (hyper_mkdir(path, mode) < 0)
return -1; goto fail;
*p = '/'; *p = '/';
} }
if (mkdir(path, 0755) < 0 && errno != EEXIST) fprintf(stdout, "create directory %s\n", path);
return -1; if (mkdir(path, mode) < 0 && errno != EEXIST) {
perror("failed to create directory");
goto fail;
}
out:
free(path);
return 0; return 0;
fail:
free(path);
return -1;
}
void online_cpu(void)
{
DIR *dir = opendir("/sys/devices/system/cpu");
if (dir == NULL) {
fprintf(stderr, "open dir /sys/devices/system/cpu failed\n");
return;
}
printf("online_cpu()\n");
for (;;) {
int num;
int ret;
char path[256];
int fd;
struct dirent *entry = readdir(dir);
if (entry == NULL)
break;
if (entry->d_type != DT_DIR)
continue;
ret = sscanf(entry->d_name, "cpu%d", &num);
if (ret < 1 || num == 0) /* skip none cpu%d and cpu0 */
continue;
sprintf(path, "/sys/devices/system/cpu/%s/online", entry->d_name);
fd = open(path, O_RDWR);
if (fd < 0) {
fprintf(stderr, "open %s failed\n", path);
continue;
}
printf("try to online %s\n", entry->d_name);
ret = write(fd, "1", sizeof("1"));
printf("online %s result: %s\n", entry->d_name, ret == 2 ? "success" : "failed");
close(fd);
}
closedir(dir);
}
void online_memory(void)
{
DIR *dir = opendir("/sys/devices/system/memory");
if (dir == NULL) {
fprintf(stderr, "open dir /sys/devices/system/memory failed\n");
return;
}
printf("online_memory()\n");
for (;;) {
int num;
int ret;
char path[256];
int fd;
struct dirent *entry = readdir(dir);
if (entry == NULL)
break;
if (entry->d_type != DT_DIR)
continue;
ret = sscanf(entry->d_name, "memory%d", &num);
if (ret < 1 || num == 0) /* skip none memory%d and memory0 */
continue;
sprintf(path, "/sys/devices/system/memory/%s/online", entry->d_name);
fd = open(path, O_RDWR);
if (fd < 0) {
fprintf(stderr, "open %s failed\n", path);
continue;
}
printf("try to online %s\n", entry->d_name);
ret = write(fd, "1", sizeof("1"));
printf("online %s result: %s\n", entry->d_name, ret == 2 ? "success" : "failed");
close(fd);
}
closedir(dir);
} }
#if WITH_VBOX #if WITH_VBOX
@@ -358,21 +626,6 @@ int hyper_setfd_nonblock(int fd)
return flags; return flags;
} }
int hyper_socketpair(int domain, int type, int protocol, int sv[2])
{
if (socketpair(domain, type, protocol, sv) < 0) {
perror("socketpair failed");
return -1;
}
if (hyper_setfd_cloexec(sv[0]) < 0 ||
hyper_setfd_cloexec(sv[1]) < 0) {
return -1;
}
return 0;
}
static void hyper_unmount_all(void) static void hyper_unmount_all(void)
{ {
FILE *mtab; FILE *mtab;
@@ -413,14 +666,46 @@ static void hyper_unmount_all(void)
fprintf(stdout, ("umount %s: %s failed\n"), fprintf(stdout, ("umount %s: %s failed\n"),
filesys, strerror(errno)); filesys, strerror(errno));
} }
free(filesys);
mntlist[i] = NULL;
} }
sync(); sync();
} }
void hyper_shutdown() void hyper_shutdown(int error)
{ {
hyper_send_msg_block(ctl.chan.fd, ACK, 0, NULL); hyper_send_msg_block(ctl.chan.fd, error?ERROR:ACK, 0, NULL);
hyper_unmount_all(); hyper_unmount_all();
reboot(LINUX_REBOOT_CMD_POWER_OFF); reboot(LINUX_REBOOT_CMD_POWER_OFF);
} }
int hyper_cmd(char *cmd)
{
int pid, status;
pid = fork();
if (pid < 0) {
perror("fail to fork");
return -1;
} else if (pid > 0) {
if (waitpid(pid, &status, 0) <= 0) {
perror("waiting fork cmd failed");
return -1;
}
if (WIFEXITED(status)) {
int ret = WEXITSTATUS(status);
fprintf(stdout, "%s cmd exit normally, status %" PRIu8 "\n", cmd, ret);
if (ret == 0)
return 0;
}
fprintf(stdout, "cmd %s exit unexpectedly, status %" PRIu8 "\n", cmd, status);
return -1;
} else {
fprintf(stdout, "executing cmd %s\n", cmd);
execlp("/busybox", "sh", "-c", cmd, NULL);
}
return -1;
}
+17 -4
View File
@@ -2,6 +2,8 @@
#define _UTIL_H_ #define _UTIL_H_
#include <stdio.h> #include <stdio.h>
#include <grp.h>
#include <pwd.h>
#include "../config.h" #include "../config.h"
struct hyper_pod; struct hyper_pod;
@@ -9,22 +11,33 @@ struct env;
#ifdef WITH_DEBUG #ifdef WITH_DEBUG
#define dprintf(fmt, ...) \ #define dprintf(fmt, ...) \
fprintf(stdout, fmt, ##_VA_ARGS__) fprintf(stdout, fmt, ##__VA_ARGS__)
#else #else
#define dprintf(fmr, ...) #define dprintf(fmr, ...)
#endif #endif
char *read_cmdline(void); char *read_cmdline(void);
int hyper_setup_env(struct env *envs, int num); int hyper_setup_env(struct env *envs, int num);
int hyper_find_sd(char *prefix, char *addr, char **dev); int hyper_find_sd(char *addr, char **dev);
int hyper_list_dir(char *path); int hyper_list_dir(char *path);
int hyper_mkdir(char *path); int hyper_copy_dir(char *src, char *dst);
void hyper_sync_time_hctosys();
void online_cpu(void);
void online_memory(void);
int hyper_cmd(char *cmd);
int hyper_create_file(const char *hyper_path);
void hyper_filize(char *hyper_path);
int hyper_mkdir(char *path, mode_t mode);
int hyper_write_file(const char *path, const char *value, size_t len);
int hyper_open_channel(char *channel, int mode); int hyper_open_channel(char *channel, int mode);
int hyper_open_serial_dev(char *tty); int hyper_open_serial_dev(char *tty);
int hyper_setfd_cloexec(int fd); int hyper_setfd_cloexec(int fd);
int hyper_setfd_block(int fd); int hyper_setfd_block(int fd);
int hyper_setfd_nonblock(int fd); int hyper_setfd_nonblock(int fd);
int hyper_socketpair(int domain, int type, int protocol, int sv[2]); int hyper_socketpair(int domain, int type, int protocol, int sv[2]);
void hyper_shutdown(void); void hyper_shutdown(int ack);
int hyper_insmod(char *module); int hyper_insmod(char *module);
struct passwd *hyper_getpwnam(const char *name);
struct group *hyper_getgrnam(const char *name);
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
#endif #endif