mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-09-06 13:41:44 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f359cb9468 | ||
|
|
3de74e927c | ||
|
|
7b54d5c9da | ||
|
|
1e4711d898 | ||
|
|
cb71f43ed1 | ||
|
|
c72276b004 | ||
|
|
5735f9f674 | ||
|
|
de0c2c97e4 | ||
|
|
8a86dd1f51 | ||
|
|
5ba9b2550d | ||
|
|
da986b4a3a | ||
|
|
2f4626dde2 | ||
|
|
bf61d6306e | ||
|
|
74f6930073 | ||
|
|
0c05c999e3 | ||
|
|
97099eb46e | ||
|
|
b28a02fa0d | ||
|
|
9a6738d84d | ||
|
|
d3cfa23dde | ||
|
|
9bfb3be414 | ||
|
|
ae2d491c20 | ||
|
|
b0a601793e | ||
|
|
19f1dc012e | ||
|
|
87b1a5c29a | ||
|
|
4a63bceb67 | ||
|
|
b2f6b89ea6 | ||
|
|
db4f364510 | ||
|
|
2ccea842bd | ||
|
|
3197bcad45 | ||
|
|
3bed96c176 | ||
|
|
eecb4c5612 | ||
|
|
c015887bb6 | ||
|
|
2169309145 | ||
|
|
c5d25b6f5f | ||
|
|
da6b36411a | ||
|
|
06d10f2844 | ||
|
|
70d35640b9 | ||
|
|
1f501c5417 | ||
|
|
1c21bb2e6f | ||
|
|
b6c6e1f991 | ||
|
|
98059369b8 | ||
|
|
03187117e1 | ||
|
|
54aed5efc5 | ||
|
|
98b8211ddc | ||
|
|
cd9a8f4306 | ||
|
|
bb550c2444 | ||
|
|
00308d00b5 | ||
|
|
e255de660d | ||
|
|
ca004ec273 | ||
|
|
52aca5a860 | ||
|
|
5fcac6f0bb | ||
|
|
216bce6fe0 | ||
|
|
e8381942d4 | ||
|
|
51dc391bc0 | ||
|
|
73a9c3e8e9 | ||
|
|
505ad4ddb0 | ||
|
|
20158b9033 | ||
|
|
1e6dffd36f | ||
|
|
d919414192 | ||
|
|
b15d771a56 | ||
|
|
b99768db28 | ||
|
|
1a612982e8 | ||
|
|
3f034fec04 | ||
|
|
831113b7d0 | ||
|
|
64aeb1ceca | ||
|
|
11c7507eed | ||
|
|
828204c1cf | ||
|
|
94720f4ace | ||
|
|
12a797cb9e | ||
|
|
7856628d8a | ||
|
|
193c1cc97e | ||
|
|
c3eee6616f | ||
|
|
3d57690daa | ||
|
|
9ca23869fc | ||
|
|
72996cd5e8 | ||
|
|
ab6ff1d2bd | ||
|
|
40f04580ec | ||
|
|
286e0f9c8f | ||
|
|
6aa71c3bd9 | ||
|
|
01a958b209 | ||
|
|
bbba8776ff | ||
|
|
34b6af632a | ||
|
|
99c593a8be | ||
|
|
57b130adbb | ||
|
|
558adb04ab | ||
|
|
684dd342d7 | ||
|
|
53bdafd2c5 | ||
|
|
f54f77ccaa | ||
|
|
6065205cb2 | ||
|
|
071a0c2b30 | ||
|
|
c4f9764556 | ||
|
|
99fe992d31 | ||
|
|
837016a417 | ||
|
|
d7dd250195 | ||
|
|
8626dfc79e | ||
|
|
75e23882bf | ||
|
|
95394c8e5a | ||
|
|
623d667fa0 | ||
|
|
7279227474 | ||
|
|
d2daea2927 | ||
|
|
f4493e59f9 | ||
|
|
9cca6ef2f9 | ||
|
|
aea6029ba1 | ||
|
|
fcc973cda6 | ||
|
|
0896a874c7 | ||
|
|
53ffb48e0a | ||
|
|
a70c3cfb54 | ||
|
|
1a4a6794e0 | ||
|
|
8024730027 | ||
|
|
211eb96eb6 | ||
|
|
5b7069c8b4 | ||
|
|
ece6aa1a79 | ||
|
|
185cfb9fe4 | ||
|
|
c8b2fee21c | ||
|
|
9ce56b757e | ||
|
|
72fc9ade82 | ||
|
|
05c85499bc | ||
|
|
3785a4d02c | ||
|
|
d74aaa326d | ||
|
|
9615c24fca | ||
|
|
783d711be1 | ||
|
|
30b3bf772b | ||
|
|
d69a74be22 | ||
|
|
908797e672 | ||
|
|
cf2267cff2 | ||
|
|
42ba6daf6d | ||
|
|
61b2963d0d | ||
|
|
c92d2d6430 | ||
|
|
274fa5cd84 | ||
|
|
baa07ce3f9 | ||
|
|
402a930af0 | ||
|
|
4475e2db1b | ||
|
|
2c12120713 | ||
|
|
84207a3f97 | ||
|
|
ab1c293818 | ||
|
|
3fbba94a0f | ||
|
|
a9b7fed072 | ||
|
|
ad196e2fe3 | ||
|
|
0c3b80fdbd | ||
|
|
c835eb9dfe | ||
|
|
99319c29a6 | ||
|
|
354c4f44b6 | ||
|
|
048ee7ba27 | ||
|
|
9eef10d3c3 | ||
|
|
ecdc3cd339 | ||
|
|
4f5b747c2b | ||
|
|
a0bc0851d6 | ||
|
|
c68c7b76d1 | ||
|
|
9590958aae | ||
|
|
d3199fcc60 | ||
|
|
4b45b28122 | ||
|
|
e458707966 | ||
|
|
3554b8ef0b | ||
|
|
48e7b27737 | ||
|
|
1cff207e67 | ||
|
|
aa50e5812b | ||
|
|
64cbfd2a0b | ||
|
|
e487303205 | ||
|
|
5a91148a37 | ||
|
|
6a56562120 | ||
|
|
8803fa8ccb | ||
|
|
90998a9b21 | ||
|
|
5e945d507e | ||
|
|
c1023f414f | ||
|
|
e737392fc4 | ||
|
|
01a09c9b8f | ||
|
|
a524b04f8c | ||
|
|
2332d39620 | ||
|
|
bc28dfedf8 | ||
|
|
09c0a1b41b | ||
|
|
b441c1bffe | ||
|
|
5be2a71a84 | ||
|
|
8766f77f24 | ||
|
|
e4beaad672 | ||
|
|
7f6056fc4c | ||
|
|
5ceb9b8906 | ||
|
|
2ace93e881 | ||
|
|
abd52a4ae2 | ||
|
|
76bccbd261 | ||
|
|
8f70de4d49 | ||
|
|
ea196f786d | ||
|
|
ced3b9dc53 | ||
|
|
5ca0595e4f | ||
|
|
53cd58a121 | ||
|
|
0a86f73869 | ||
|
|
12ba0a42b2 | ||
|
|
1ad3ffcf63 | ||
|
|
5f9a7ee0a2 | ||
|
|
b0c0255148 | ||
|
|
6b67c6a296 | ||
|
|
0017a6110f | ||
|
|
6bbb9ac512 | ||
|
|
6feb864e30 | ||
|
|
6ff04bf83d | ||
|
|
80778ddd25 | ||
|
|
c455e8bc75 | ||
|
|
411cffdeec | ||
|
|
04689c4138 | ||
|
|
50928fc1ef | ||
|
|
20c34a4312 | ||
|
|
fdd2634721 | ||
|
|
b043ac88e1 | ||
|
|
5c18914f2a | ||
|
|
a0e1ecb2ba | ||
|
|
5279ef3f96 | ||
|
|
36fb6e6877 | ||
|
|
6632db44ae | ||
|
|
613a5a19db | ||
|
|
21d63485b1 | ||
|
|
eaae1ae3fb | ||
|
|
333263b344 | ||
|
|
50db29c634 | ||
|
|
fe5c6c29e1 | ||
|
|
34d842901d | ||
|
|
a94833c482 | ||
|
|
0676ed3227 | ||
|
|
e12e480f79 | ||
|
|
3fa27e7464 | ||
|
|
013cbb7e1a | ||
|
|
97aee2acb0 | ||
|
|
43c2336d7f | ||
|
|
220677d76d | ||
|
|
0f396470ff | ||
|
|
94266c5111 | ||
|
|
0b3370f6fa | ||
|
|
c5abeccb65 | ||
|
|
aa7772b36c | ||
|
|
f47d84cf24 | ||
|
|
d97485cfc0 | ||
|
|
4fc4ac0c46 | ||
|
|
bd41fcfbe6 | ||
|
|
bd9623c892 | ||
|
|
00e65b239c | ||
|
|
b654a0fbd3 | ||
|
|
2f757d249d | ||
|
|
db33f31dc1 | ||
|
|
661dcdda07 | ||
|
|
22a65f7666 | ||
|
|
1ce35da941 | ||
|
|
e6cffd9add | ||
|
|
213a00ec5e | ||
|
|
c03c057a42 | ||
|
|
73849713e8 | ||
|
|
0610a4e156 | ||
|
|
29efaadf0a | ||
|
|
02ba85f8e0 | ||
|
|
d563b3ecb0 | ||
|
|
ce0ab6b836 | ||
|
|
feedb0808b | ||
|
|
c14737f39c | ||
|
|
4b6375a4a4 | ||
|
|
bfa1af2101 | ||
|
|
a866e257fd | ||
|
|
d34656475e | ||
|
|
2b1edeceb4 | ||
|
|
f49d1247d2 | ||
|
|
ee697391d6 | ||
|
|
93c02c012f | ||
|
|
545258bd26 | ||
|
|
9611ecf356 | ||
|
|
0887e9a6de | ||
|
|
a2086298f6 | ||
|
|
b7c88467e2 | ||
|
|
0c997dbe85 | ||
|
|
6d3265a7fb | ||
|
|
a46092a90a | ||
|
|
25da342f75 | ||
|
|
c3160aea0a | ||
|
|
7bbc240cae | ||
|
|
1958e11f45 | ||
|
|
738a11dcdc | ||
|
|
280bc617d0 | ||
|
|
252def6bab | ||
|
|
4361f071e8 | ||
|
|
7ef8099916 | ||
|
|
1558b44495 | ||
|
|
0c42ea97a4 | ||
|
|
51f2a45217 | ||
|
|
3b0ff1d7ca | ||
|
|
62dea1454d | ||
|
|
b5f8137499 | ||
|
|
e64268427d | ||
|
|
99ee15c731 | ||
|
|
dfa392edb7 | ||
|
|
7075847ef4 | ||
|
|
19da0a2068 | ||
|
|
180339f16b | ||
|
|
c86afd1a5c | ||
|
|
910a42d647 | ||
|
|
18abe7d9e1 | ||
|
|
ae5338bde5 | ||
|
|
7843001aa7 | ||
|
|
cff19ec212 | ||
|
|
c126e40795 | ||
|
|
11c4d7311b | ||
|
|
1f2b1f5880 | ||
|
|
14f9ba5c3f | ||
|
|
26183926a3 | ||
|
|
a7a3c52c88 | ||
|
|
350997b03c | ||
|
|
48c6e2248a | ||
|
|
08fcf381e8 | ||
|
|
f3f78303b1 | ||
|
|
555bc46d14 | ||
|
|
b14f68378d | ||
|
|
8553460afe | ||
|
|
16cf97584c | ||
|
|
a5680759eb | ||
|
|
b6e073d03c | ||
|
|
d7752ebd8b | ||
|
|
fdc9364062 | ||
|
|
da47929b6a | ||
|
|
3f663e7a4e | ||
|
|
3453f63787 | ||
|
|
8cd46388e5 | ||
|
|
5f819dc68a | ||
|
|
14aa9eaa39 | ||
|
|
c0585278d0 | ||
|
|
d9a36a889e | ||
|
|
788e80ce39 | ||
|
|
68b31dddd5 | ||
|
|
f0d9fc7bce | ||
|
|
684e85cc5e | ||
|
|
d45be919cd | ||
|
|
5c3bd1b19f | ||
|
|
600e8dd3c8 | ||
|
|
08764d5bbc | ||
|
|
749387bbfa | ||
|
|
88bb908c76 | ||
|
|
d260dda29e | ||
|
|
a8362c1a70 | ||
|
|
87fa294a42 | ||
|
|
330c46cdb2 | ||
|
|
27f4b56e71 | ||
|
|
2262bc18fe | ||
|
|
bc0e688f96 | ||
|
|
2fb02c57b6 | ||
|
|
bf0f360935 | ||
|
|
6976865176 | ||
|
|
c862b89079 | ||
|
|
6a15977238 | ||
|
|
7d6468f70b | ||
|
|
ed9a351518 | ||
|
|
d4b3e0ad62 | ||
|
|
1bd2d3d992 | ||
|
|
ce452d5759 | ||
|
|
56cb24bd0d | ||
|
|
c7b46b71a0 | ||
|
|
e7e6b98958 | ||
|
|
2f27b48f7b | ||
|
|
04a501edb7 | ||
|
|
01f07fb952 |
@@ -14,6 +14,7 @@ build/cbfs.rom
|
||||
build/root/*
|
||||
build/*iso
|
||||
build/daemon
|
||||
build/kernel_config.old
|
||||
build/.*
|
||||
src/.*
|
||||
Makefile
|
||||
|
||||
@@ -4,3 +4,5 @@ initrd-local:
|
||||
@echo finish make initrd
|
||||
cbfs-local:
|
||||
@echo finish make cbfs
|
||||
kernel-local:
|
||||
@echo finish make kernel
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
# The init Task for Hyper
|
||||
# The init Task for HyperContainer
|
||||
|
||||
You can get 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
|
||||
|
||||
clone this repo, and make sure have build-essentials installed. Go into the working copy and
|
||||
clone this repo, and make sure you have build-essentials installed. Go into the working copy and
|
||||
|
||||
> ./autogen.sh
|
||||
> ./configure
|
||||
> make
|
||||
|
||||
Then you can find `hyper-initrd.img` in build directory, together with a pre-build kernel.
|
||||
Then you can find `hyper-initrd.img` in the build directory, together with a pre-built kernel.
|
||||
|
||||
If you want to get the boot disk file for VirtaulBox, please reconfigure with flag --with-vbox,
|
||||
If you want to get the boot disk file for VirtualBox, please reconfigure with flag --with-vbox,
|
||||
|
||||
> ./configure --with-vbox
|
||||
> make
|
||||
|
||||
Then you can find `hyper-vbox-bootimage.iso` in build directory, booting from this iso will
|
||||
Then you can find `hyper-vbox-bootimage.iso` in the build directory. Booting from this iso will
|
||||
bring you to the hyper world.
|
||||
|
||||
@@ -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
|
||||
@@ -10,3 +10,10 @@ endif
|
||||
|
||||
cbfs-local:
|
||||
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
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
+916
-215
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
|
||||
|
||||
Executable
BIN
Binary file not shown.
+15
-9
@@ -1,18 +1,22 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -rf root
|
||||
mkdir root
|
||||
rm -rf /tmp/hyperstart-rootfs
|
||||
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
|
||||
arr=(${line// / })
|
||||
|
||||
for lib in ${arr[@]}
|
||||
do
|
||||
if [ "${lib:0:1}" = "/" ]; then
|
||||
dir=root`dirname $lib`
|
||||
dir=/tmp/hyperstart-rootfs`dirname $lib`
|
||||
mkdir -p "${dir}"
|
||||
cp -f $lib $dir
|
||||
fi
|
||||
@@ -21,13 +25,13 @@ done
|
||||
|
||||
if [ "$1"x = "vbox"x ]; then
|
||||
echo "build initrd for vbox"
|
||||
cp ./vbox/driver/* ./root
|
||||
cp ./vbox/driver/* /tmp/hyperstart-rootfs
|
||||
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 ../
|
||||
rm -rf ./root
|
||||
rm -rf /tmp/hyperstart-rootfs
|
||||
|
||||
if [ "$1"x = "cbfs"x ]; then
|
||||
echo "build cbfs"
|
||||
@@ -36,9 +40,11 @@ if [ "$1"x = "cbfs"x ]; then
|
||||
|
||||
mkdir .cbfs
|
||||
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 hyper-initrd.img -n initrd -t raw
|
||||
echo 'console=ttyS0 panic=1 no_timer_check' > .cbfs/cmdline
|
||||
cbfstool .cbfs/cbfs.rom add -f .cbfs/cmdline -n cmdline -t raw
|
||||
cp .cbfs/cbfs.rom ./
|
||||
rm -rf .cbfs
|
||||
exit 0
|
||||
|
||||
Binary file not shown.
+3
-2
@@ -2,9 +2,9 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([hyperstart], [0.2], [www.hyper.sh])
|
||||
AC_INIT([hyperstart], [0.6.2], [www.hyper.sh])
|
||||
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_HEADERS([config.h])
|
||||
|
||||
@@ -32,6 +32,7 @@ AC_TYPE_UINT8_T
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
AC_CHECK_FUNCS([dup2 memmove memset mkdir setenv socket strchr strdup strrchr strtoul], [fail=0], [fail=1])
|
||||
AC_CHECK_FUNCS([setns])
|
||||
|
||||
if test "$fail" = "1" ; then
|
||||
AC_MSG_ERROR(Unable to find necessary functions)
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
AM_CFLAGS = -Wall
|
||||
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
|
||||
|
||||
+496
-263
@@ -7,6 +7,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#include <mntent.h>
|
||||
#include <signal.h>
|
||||
@@ -16,18 +17,79 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "hyper.h"
|
||||
#include "parse.h"
|
||||
#include "syscall.h"
|
||||
|
||||
static int container_setup_env(struct hyper_container *container)
|
||||
static int container_populate_volume(char *src, char *dest)
|
||||
{
|
||||
int i;
|
||||
struct env *env;
|
||||
struct stat st;
|
||||
|
||||
for (i = 0; i < container->envs_num; i++) {
|
||||
env = &container->envs[i];
|
||||
fprintf(stdout, "populate volumes from %s to %s\n", src, dest);
|
||||
/* FIXME: check if has data in volume, (except lost+found) */
|
||||
|
||||
setenv(env->env, env->value, 1);
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -38,127 +100,113 @@ static int container_setup_volume(struct hyper_container *container)
|
||||
struct volume *vol;
|
||||
|
||||
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];
|
||||
|
||||
sprintf(dev, "/.oldroot/dev/%s", vol->device);
|
||||
if (vol->scsiaddr)
|
||||
hyper_find_sd(vol->scsiaddr, &vol->device);
|
||||
|
||||
sprintf(dev, "/dev/%s", vol->device);
|
||||
sprintf(path, "/tmp/%s", vol->mountpoint);
|
||||
sprintf(mountpoint, "./%s", vol->mountpoint);
|
||||
|
||||
fprintf(stdout, "mount %s to %s, tmp path %s\n",
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(dev, path, vol->fstype, 0, NULL) < 0) {
|
||||
perror("mount volume device faled");
|
||||
if (!strncmp(vol->fstype, "xfs", strlen("xfs")))
|
||||
options = "nouuid";
|
||||
|
||||
if (mount(dev, path, vol->fstype, 0, options) < 0) {
|
||||
perror("mount volume device failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount volume device faled");
|
||||
sprintf(volume, "/%s/_data", path);
|
||||
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;
|
||||
}
|
||||
|
||||
if (vol->readonly &&
|
||||
mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
||||
perror("mount fsmap faled");
|
||||
mount(volume, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
||||
perror("mount fsmap failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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", 0, NULL) < 0 ||
|
||||
mount("sysfs", "/sys", "sysfs", 0, NULL) < 0 ||
|
||||
mount("devtmpfs", "/dev", "devtmpfs", 0, NULL) < 0) {
|
||||
perror("mount basic filesystem for container 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++) {
|
||||
struct stat st;
|
||||
char *src, path[512], volume[512];
|
||||
struct fsmap *map = &container->maps[i];
|
||||
char mountpoint[512];
|
||||
|
||||
map = &container->maps[i];
|
||||
|
||||
sprintf(src, "/.oldroot/tmp/hyper/shared/%s", map->source);
|
||||
fprintf(stdout, "mount %s to %s\n", src, map->path);
|
||||
sprintf(path, "/tmp/hyper/shared/%s", map->source);
|
||||
sprintf(mountpoint, "./%s", map->path);
|
||||
fprintf(stdout, "mount %s to %s\n", path, mountpoint);
|
||||
|
||||
src = path;
|
||||
stat(src, &st);
|
||||
|
||||
if (st.st_mode & S_IFDIR) {
|
||||
if (hyper_mkdir(map->path) < 0) {
|
||||
if (hyper_mkdir(mountpoint, 0755) < 0) {
|
||||
perror("create map dir failed");
|
||||
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 {
|
||||
fd = open(map->path, O_CREAT|O_WRONLY, 0755);
|
||||
int fd = open(mountpoint, O_CREAT|O_WRONLY, 0755);
|
||||
if (fd < 0) {
|
||||
perror("create map file failed");
|
||||
continue;
|
||||
@@ -166,16 +214,224 @@ static int container_setup_mount(struct hyper_container *container)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (mount(src, map->path, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount fsmap faled");
|
||||
if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount fsmap failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map->readonly == 0)
|
||||
continue;
|
||||
|
||||
if (mount(src, map->path, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
||||
perror("mount fsmap faled");
|
||||
if (mount(src, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
||||
perror("mount fsmap failed");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
int i;
|
||||
struct sysctl *sys;
|
||||
|
||||
for (i = 0; i < container->sys_num; i++) {
|
||||
char path[256];
|
||||
|
||||
sys = &container->sys[i];
|
||||
|
||||
sprintf(path, "/proc/sys/%s", sys->path);
|
||||
fprintf(stdout, "sysctl %s value %s\n", sys->path, sys->value);
|
||||
|
||||
if (hyper_write_file(path, sys->value, strlen(sys->value)) < 0) {
|
||||
fprintf(stderr, "sysctl: write %s to %s failed\n", sys->value, path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_setup_dns(struct hyper_container *container)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *src = "/tmp/hyper/resolv.conf";
|
||||
|
||||
if (stat(src, &st) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stdout, "no dns configured\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
perror("stat resolve.conf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hyper_mkdir("./etc", 0755);
|
||||
|
||||
fd = open("./etc/resolv.conf", O_CREAT| O_WRONLY, 0644);
|
||||
if (fd < 0) {
|
||||
perror("create /etc/resolv.conf failed");
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (mount(src, "./etc/resolv.conf", NULL, MS_BIND, NULL) < 0) {
|
||||
perror("bind to /etc/resolv.conf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -183,19 +439,14 @@ static int container_setup_mount(struct hyper_container *container)
|
||||
|
||||
static int container_setup_workdir(struct hyper_container *container)
|
||||
{
|
||||
if (container->workdir && chdir(container->workdir) < 0) {
|
||||
perror("change work directory failed");
|
||||
return -1;
|
||||
if (container->initialize) {
|
||||
// create workdir
|
||||
return hyper_mkdir(container->exec.workdir, 0755);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
struct dirent **list;
|
||||
@@ -243,18 +494,21 @@ static int hyper_rescan_scsi(void)
|
||||
|
||||
struct hyper_container_arg {
|
||||
struct hyper_container *c;
|
||||
struct hyper_pod *pod;
|
||||
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 *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 (container->exec.argv == NULL) {
|
||||
fprintf(stdout, "no cmd!\n");
|
||||
if (hyper_enter_sandbox(arg->pod, -1) < 0) {
|
||||
perror("enter sandbox failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -263,11 +517,6 @@ static int hyper_container_init(void *data)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (container_setup_env(container) < 0) {
|
||||
fprintf(stdout, "setup env failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
|
||||
perror("mount SLAVE failed");
|
||||
goto fail;
|
||||
@@ -279,7 +528,7 @@ static int hyper_container_init(void *data)
|
||||
}
|
||||
|
||||
sprintf(root, "/tmp/hyper/%s/root/", container->id);
|
||||
if (hyper_mkdir(root) < 0) {
|
||||
if (hyper_mkdir(root, 0755) < 0) {
|
||||
perror("make root directroy failed");
|
||||
goto fail;
|
||||
}
|
||||
@@ -288,11 +537,21 @@ static int hyper_container_init(void *data)
|
||||
|
||||
if (container->fstype) {
|
||||
char dev[128];
|
||||
char *options = NULL;
|
||||
|
||||
if (container->scsiaddr) {
|
||||
free(container->image);
|
||||
container->image = NULL;
|
||||
hyper_find_sd(container->scsiaddr, &container->image);
|
||||
}
|
||||
|
||||
sprintf(dev, "/dev/%s", container->image);
|
||||
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");
|
||||
goto fail;
|
||||
}
|
||||
@@ -311,31 +570,54 @@ static int hyper_container_init(void *data)
|
||||
fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
|
||||
root, container->rootfs, container->exec.argv[0]);
|
||||
|
||||
sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs);
|
||||
if (hyper_mkdir(oldroot) < 0) {
|
||||
perror("make oldroot directroy failed");
|
||||
sprintf(rootfs, "%s/%s/", root, container->rootfs);
|
||||
if (mount(rootfs, rootfs, NULL, MS_BIND|MS_REC, NULL) < 0) {
|
||||
perror("failed to bind rootfs");
|
||||
goto fail;
|
||||
}
|
||||
chdir(rootfs);
|
||||
|
||||
/*
|
||||
* Recreate dns resolver iif configured by pod spec. Other cases
|
||||
* are handled by hyperd instead.
|
||||
*/
|
||||
setup_dns = arg->pod->dns != NULL && arg->pod->d_num > 0;
|
||||
if (container_setup_init_layer(container, setup_dns) < 0) {
|
||||
fprintf(stderr, "container sets up init layer failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mount("/", oldroot, NULL, MS_BIND|MS_REC, NULL) < 0) {
|
||||
perror("bind oldroot failed");
|
||||
if (container_setup_mount(container) < 0) {
|
||||
fprintf(stderr, "container sets up mount failed\n");
|
||||
goto fail;
|
||||
}
|
||||
/* reuse oldroot array */
|
||||
sprintf(oldroot, "%s/%s/", root, container->rootfs);
|
||||
/* pivot_root won't work, see
|
||||
* Documention/filesystem/ramfs-rootfs-initramfs.txt */
|
||||
chroot(oldroot);
|
||||
|
||||
chdir("/");
|
||||
// ignore error of setup modules
|
||||
container_setup_modules(container);
|
||||
|
||||
if (container_setup_volume(container) < 0) {
|
||||
fprintf(stderr, "container sets up voulme failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (container_setup_mount(container) < 0) {
|
||||
fprintf(stderr, "container sets up mount ns failed\n");
|
||||
if (container_setup_dns(container) < 0) {
|
||||
fprintf(stderr, "container sets up dns failed\n");
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -344,198 +626,149 @@ static int hyper_container_init(void *data)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
container_unmount_oldroot("/.oldroot");
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if (container_setup_tty(arg->pipe[1], container) < 0) {
|
||||
fprintf(stdout, "setup tty failed\n");
|
||||
/* wait for ns-opened ready message */
|
||||
if (hyper_get_type(arg->pipens[0], &type) < 0 || type != READY) {
|
||||
fprintf(stderr, "wait for /proc/self/ns/mnt opened failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(arg->pipe[0]);
|
||||
close(arg->pipe[1]);
|
||||
|
||||
execvp(container->exec.argv[0], container->exec.argv);
|
||||
perror("exec container command failed");
|
||||
|
||||
_exit(-1);
|
||||
hyper_send_type(arg->pipe[1], READY);
|
||||
fflush(NULL);
|
||||
_exit(0);
|
||||
|
||||
fail:
|
||||
container->exec.code = -1;
|
||||
hyper_send_type_block(arg->pipe[1], ERROR, 0);
|
||||
_exit(-1);
|
||||
hyper_send_type(arg->pipe[1], ERROR);
|
||||
_exit(125);
|
||||
}
|
||||
|
||||
int hyper_start_container(struct hyper_container *container)
|
||||
static int hyper_setup_pty(struct hyper_container *c)
|
||||
{
|
||||
int stacksize = getpagesize() * 4;
|
||||
char root[512];
|
||||
|
||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||
|
||||
if (hyper_mkdir(root, 0755) < 0) {
|
||||
perror("make container pts directroy failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("devpts", root, "devpts", MS_NOSUID,
|
||||
"newinstance,ptmxmode=0666,mode=0620") < 0) {
|
||||
perror("mount devpts failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod)
|
||||
{
|
||||
int stacksize = getpagesize() * 42;
|
||||
struct hyper_container_arg arg = {
|
||||
.c = container,
|
||||
.c = container,
|
||||
.pod = pod,
|
||||
.pipe = {-1, -1},
|
||||
.pipens = {-1, -1},
|
||||
};
|
||||
int flags = CLONE_NEWNS | SIGCHLD;
|
||||
uint32_t type;
|
||||
char path[128];
|
||||
void *stack;
|
||||
uint32_t type;
|
||||
int pid;
|
||||
|
||||
if (container->image == NULL || container->exec.argv == NULL) {
|
||||
fprintf(stdout, "container root image %s, argv %p\n",
|
||||
container->image, container->exec.argv);
|
||||
if (pipe2(arg.pipe, O_CLOEXEC) < 0 || pipe2(arg.pipens, O_CLOEXEC) < 0) {
|
||||
perror("create pipe between pod init execcmd failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (socketpair(PF_UNIX, SOCK_STREAM, 0, arg.pipe) < 0) {
|
||||
perror("create pipe between pod init execcmd failed");
|
||||
if (hyper_setup_container_portmapping(container, pod) < 0) {
|
||||
perror("fail to setup port mapping for container");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (hyper_setup_pty(container) < 0) {
|
||||
fprintf(stderr, "setup pty device for container failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
stack = malloc(stacksize);
|
||||
if (stack == NULL) {
|
||||
perror("fail to allocate stack for container init");
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
pid = clone(hyper_container_init, stack + stacksize, flags, &arg);
|
||||
pid = clone(hyper_setup_container_rootfs, stack + stacksize, flags, &arg);
|
||||
free(stack);
|
||||
if (pid < 0) {
|
||||
perror("create child process failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
container->exec.pid = pid;
|
||||
sprintf(path, "/proc/%d/ns/mnt", pid);
|
||||
container->ns = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (container->ns < 0) {
|
||||
perror("open container mount ns failed");
|
||||
goto fail;
|
||||
}
|
||||
hyper_send_type(arg.pipens[1], READY);
|
||||
|
||||
/* wait for ready message */
|
||||
if (hyper_get_type_block(arg.pipe[0], &type) < 0 || type != READY) {
|
||||
fprintf(stdout, "wait for container started failed\n");
|
||||
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
|
||||
fprintf(stderr, "wait for setup container rootfs failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(arg.pipe[0]);
|
||||
close(arg.pipe[1]);
|
||||
|
||||
fprintf(stdout, "container %s init pid is %d\n", container->id, pid);
|
||||
close(arg.pipens[0]);
|
||||
close(arg.pipens[1]);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
|
||||
|
||||
container->exec.code = -1;
|
||||
close(container->ns);
|
||||
container->ns = -1;
|
||||
close(arg.pipe[0]);
|
||||
close(arg.pipe[1]);
|
||||
close(arg.pipens[0]);
|
||||
close(arg.pipens[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hyper_start_containers(struct hyper_pod *pod)
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* mount new proc directory */
|
||||
if (umount("/proc") < 0) {
|
||||
perror("umount proc filesystem failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("proc", "/proc", "proc", 0, NULL) < 0) {
|
||||
perror("mount proc filesystem failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sethostname(pod->hostname, strlen(pod->hostname)) < 0) {
|
||||
perror("set host name failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < pod->c_num; i++)
|
||||
hyper_start_container(&pod->c[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_restart_containers(struct hyper_pod *pod)
|
||||
{
|
||||
int i;
|
||||
struct hyper_container *c;
|
||||
|
||||
for (i = 0; i < pod->c_num; i++) {
|
||||
c = &pod->c[i];
|
||||
|
||||
if (hyper_start_container(c) < 0) {
|
||||
fprintf(stderr, "restart container %s failed\n", c->id);
|
||||
hyper_send_type(pod->ctl.fd, ERROR);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hyper_send_type(pod->ctl.fd, ACK) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id)
|
||||
{
|
||||
int i;
|
||||
struct hyper_container *container;
|
||||
|
||||
for (i = 0; i < pod->c_num; i++) {
|
||||
container = &pod->c[i];
|
||||
|
||||
if (strlen(container->id) != strlen(id))
|
||||
list_for_each_entry(c, &pod->containers, list) {
|
||||
if (strlen(c->id) != strlen(id))
|
||||
continue;
|
||||
|
||||
if (strncmp(container->id, id, strlen(id)))
|
||||
if (strncmp(c->id, id, strlen(id)))
|
||||
continue;
|
||||
|
||||
return container;
|
||||
return c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hyper_cleanup_container(struct hyper_pod *pod)
|
||||
void hyper_cleanup_container(struct hyper_container *c, struct hyper_pod *pod)
|
||||
{
|
||||
int i, j;
|
||||
struct hyper_container *c;
|
||||
struct volume *vol;
|
||||
struct env *env;
|
||||
struct fsmap *map;
|
||||
char root[512];
|
||||
|
||||
for (i = 0; i < pod->c_num; i++) {
|
||||
c = &pod->c[i];
|
||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
||||
perror("umount devpts failed");
|
||||
|
||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
||||
perror("umount devpts failed");
|
||||
close(c->ns);
|
||||
hyper_cleanup_container_portmapping(c, pod);
|
||||
hyper_free_container(c);
|
||||
}
|
||||
|
||||
free(c->id);
|
||||
free(c->rootfs);
|
||||
free(c->image);
|
||||
free(c->workdir);
|
||||
free(c->fstype);
|
||||
void hyper_cleanup_containers(struct hyper_pod *pod)
|
||||
{
|
||||
struct hyper_container *c, *n;
|
||||
|
||||
for (j = 0; j < c->vols_num; j++) {
|
||||
vol = &(c->vols[j]);
|
||||
free(vol->device);
|
||||
free(vol->mountpoint);
|
||||
free(vol->fstype);
|
||||
}
|
||||
free(c->vols);
|
||||
list_for_each_entry_safe(c, n, &pod->containers, list)
|
||||
hyper_cleanup_container(c, pod);
|
||||
|
||||
for (j = 0; j < c->envs_num; j++) {
|
||||
env = &(c->envs[j]);
|
||||
free(env->env);
|
||||
free(env->value);
|
||||
}
|
||||
free(c->envs);
|
||||
|
||||
for (j = 0; j < c->maps_num; j++) {
|
||||
map = &(c->maps[j]);
|
||||
free(map->source);
|
||||
free(map->path);
|
||||
}
|
||||
free(c->maps);
|
||||
}
|
||||
|
||||
free(pod->c);
|
||||
pod->c = NULL;
|
||||
pod->c_num = 0;
|
||||
pod->remains = 0;
|
||||
}
|
||||
|
||||
+31
-14
@@ -3,45 +3,62 @@
|
||||
|
||||
#include "exec.h"
|
||||
|
||||
struct env {
|
||||
char *env;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct volume {
|
||||
char *device;
|
||||
char *scsiaddr;
|
||||
char *mountpoint;
|
||||
char *fstype;
|
||||
int readonly;
|
||||
int docker;
|
||||
};
|
||||
|
||||
struct fsmap {
|
||||
char *source;
|
||||
char *path;
|
||||
int readonly;
|
||||
int docker;
|
||||
};
|
||||
|
||||
struct sysctl {
|
||||
char *path;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct port {
|
||||
int host_port;
|
||||
int container_port;
|
||||
char *protocol;
|
||||
};
|
||||
|
||||
struct hyper_container {
|
||||
struct list_head list;
|
||||
struct hyper_exec exec;
|
||||
int ns;
|
||||
uint32_t code;
|
||||
|
||||
// configs
|
||||
char *id;
|
||||
char *rootfs;
|
||||
char *image;
|
||||
char *workdir;
|
||||
char *scsiaddr;
|
||||
char *fstype;
|
||||
struct volume *vols;
|
||||
struct env *envs;
|
||||
struct fsmap *maps;
|
||||
struct sysctl *sys;
|
||||
struct port *ports;
|
||||
int vols_num;
|
||||
int envs_num;
|
||||
int maps_num;
|
||||
uint32_t code;
|
||||
struct hyper_exec exec;
|
||||
int sys_num;
|
||||
int ports_num;
|
||||
int initialize;
|
||||
};
|
||||
|
||||
struct hyper_pod;
|
||||
|
||||
int hyper_start_containers(struct hyper_pod *pod);
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
||||
int hyper_restart_containers(struct hyper_pod *pod);
|
||||
void hyper_cleanup_container(struct hyper_pod *pod);
|
||||
int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod);
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id);
|
||||
void hyper_cleanup_container(struct hyper_container *container, struct hyper_pod *pod);
|
||||
void hyper_cleanup_containers(struct hyper_pod *pod);
|
||||
void hyper_free_container(struct hyper_container *c);
|
||||
|
||||
#endif
|
||||
|
||||
+96
-67
@@ -10,24 +10,25 @@
|
||||
#include "hyper.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(de->wbuf.data);
|
||||
|
||||
memset(de, 0, sizeof(*de));
|
||||
free(he->rbuf.data);
|
||||
free(he->wbuf.data);
|
||||
close(he->fd);
|
||||
memset(he, 0, sizeof(*he));
|
||||
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 *wbuf = &de->wbuf;
|
||||
struct hyper_buf *rbuf = &he->rbuf;
|
||||
struct hyper_buf *wbuf = &he->wbuf;
|
||||
|
||||
memset(rbuf, 0, sizeof(*rbuf));
|
||||
memset(wbuf, 0, sizeof(*wbuf));
|
||||
|
||||
de->ops = ops;
|
||||
de->ptr = arg;
|
||||
he->ops = ops;
|
||||
he->ptr = arg;
|
||||
rbuf->size = ops->rbuf_size;
|
||||
wbuf->size = ops->wbuf_size;
|
||||
|
||||
@@ -50,22 +51,22 @@ int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, void *
|
||||
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 = {
|
||||
.events = flag,
|
||||
.data.ptr = de,
|
||||
.data.ptr = he,
|
||||
};
|
||||
|
||||
de->flag = flag;
|
||||
if (hyper_setfd_nonblock(de->fd) < 0) {
|
||||
he->flag = flag;
|
||||
if (hyper_setfd_nonblock(he->fd) < 0) {
|
||||
perror("set fd nonblock failed");
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
@@ -73,21 +74,21 @@ int hyper_add_event(int efd, struct hyper_event *de, int flag)
|
||||
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 = {
|
||||
.events = flag,
|
||||
.data.ptr = de,
|
||||
.data.ptr = he,
|
||||
};
|
||||
|
||||
if (de->flag == flag)
|
||||
if (he->flag == flag)
|
||||
return 0;
|
||||
|
||||
de->flag = flag;
|
||||
he->flag = flag;
|
||||
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");
|
||||
return -1;
|
||||
}
|
||||
@@ -95,39 +96,59 @@ int hyper_modify_event(int efd, struct hyper_event *de, int flag)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
uint8_t data[4];
|
||||
int offset = de->ops->len_offset;
|
||||
int offset = he->ops->len_offset;
|
||||
int end = offset + 4;
|
||||
int size;
|
||||
|
||||
fprintf(stdout, "%s\n", __func__);
|
||||
|
||||
while (hyper_getmsg_len(de, &len) < 0) {
|
||||
size = read(de->fd, buf->data + buf->get, end - buf->get);
|
||||
while (hyper_getmsg_len(he, &len) < 0) {
|
||||
size = read(he->fd, buf->data + buf->get, end - buf->get);
|
||||
if (size > 0) {
|
||||
buf->get += size;
|
||||
fprintf(stdout, "already read %" PRIu32 " bytes data\n",
|
||||
buf->get);
|
||||
|
||||
if (de->ops->ack) {
|
||||
if (he->ops->ack) {
|
||||
/* control channel, need ack */
|
||||
hyper_set_be32(data, size);
|
||||
hyper_send_msg(de->fd, NEXT, 4, data);
|
||||
hyper_send_msg(he->fd, NEXT, 4, data);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
@@ -150,15 +171,15 @@ int hyper_event_read(struct hyper_event *de)
|
||||
}
|
||||
|
||||
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) {
|
||||
buf->get += size;
|
||||
fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n",
|
||||
size, buf->get);
|
||||
if (de->ops->ack) {
|
||||
if (he->ops->ack) {
|
||||
/* control channel, need ack */
|
||||
hyper_set_be32(data, size);
|
||||
hyper_send_msg(de->fd, NEXT, 4, data);
|
||||
hyper_send_msg(he->fd, NEXT, 4, data);
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -177,7 +198,7 @@ int hyper_event_read(struct hyper_event *de)
|
||||
}
|
||||
|
||||
/* get the whole data */
|
||||
if (de->ops->handle(de, len) != 0)
|
||||
if (he->ops->handle(he, len) != 0)
|
||||
return -1;
|
||||
|
||||
/* len: length of the already get new data */
|
||||
@@ -187,14 +208,14 @@ int hyper_event_read(struct hyper_event *de)
|
||||
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;
|
||||
int size = 0;
|
||||
|
||||
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 (errno == EINTR)
|
||||
continue;
|
||||
@@ -209,46 +230,54 @@ int hyper_event_write(struct hyper_event *de)
|
||||
memmove(buf->data, buf->data + len, buf->get);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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");
|
||||
close(de->fd);
|
||||
hyper_reset_event(de);
|
||||
hyper_reset_event(he);
|
||||
}
|
||||
|
||||
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, he %p, fd %d. ops %p\n",
|
||||
__func__, event->events, he, he->fd, he->ops);
|
||||
|
||||
if (event->events & EPOLLHUP) {
|
||||
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
|
||||
__func__, de, de->fd, de->ops);
|
||||
if (de->ops->hup)
|
||||
de->ops->hup(de, efd);
|
||||
/* do not handle hup event if have in event */
|
||||
if ((event->events & EPOLLIN) && he->ops->read) {
|
||||
fprintf(stdout, "%s event EPOLLIN, he %p, fd %d, %p\n",
|
||||
__func__, he, he->fd, he->ops);
|
||||
if (he->ops->read && he->ops->read(he, efd) < 0)
|
||||
return -1;
|
||||
} else if (event->events & EPOLLHUP) {
|
||||
fprintf(stdout, "%s event EPOLLHUP, he %p, fd %d, %p\n",
|
||||
__func__, he, he->fd, he->ops);
|
||||
if (he->ops->hup)
|
||||
he->ops->hup(he, efd);
|
||||
return 0;
|
||||
} else if (event->events & EPOLLIN) {
|
||||
fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n",
|
||||
__func__, de, de->fd, de->ops);
|
||||
return de->ops->read(de);
|
||||
} else if (event->events & EPOLLOUT) {
|
||||
fprintf(stdout, "%s event EPOLLOUT, de %p, fd %d, %p\n",
|
||||
__func__, de, de->fd, de->ops);
|
||||
if (de->ops->write)
|
||||
return de->ops->write(de);
|
||||
fprintf(stderr, "warning: %p received unexpected write event\n", de);
|
||||
return 0;
|
||||
} else if (event->events & EPOLLERR) {
|
||||
fprintf(stderr, "get epoll err of not epool in event\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s get unknown event %d\n", __func__, event->events);
|
||||
return -1;
|
||||
if (event->events & EPOLLOUT) {
|
||||
fprintf(stdout, "%s event EPOLLOUT, he %p, fd %d, %p\n",
|
||||
__func__, he, he->fd, he->ops);
|
||||
if (he->ops->write && he->ops->write(he, efd) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (event->events & EPOLLERR) {
|
||||
fprintf(stderr, "get epoll err of not epool in event\n");
|
||||
if (he->ops->hup)
|
||||
he->ops->hup(he, efd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+8
-4
@@ -7,8 +7,8 @@
|
||||
struct hyper_event;
|
||||
|
||||
struct hyper_event_ops {
|
||||
int (*read)(struct hyper_event *e);
|
||||
int (*write)(struct hyper_event *e);
|
||||
int (*read)(struct hyper_event *e, int efd);
|
||||
int (*write)(struct hyper_event *e, int efd);
|
||||
int (*handle)(struct hyper_event *e, uint32_t len);
|
||||
void (*hup)(struct hyper_event *e, int efd);
|
||||
int rbuf_size;
|
||||
@@ -32,13 +32,17 @@ struct hyper_event {
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
#define FULL(buf) \
|
||||
(buf->size - buf->get <= 12)
|
||||
|
||||
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_requeue_event(int efd, struct hyper_event *ev);
|
||||
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops,
|
||||
void *arg);
|
||||
int hyper_handle_event(int efd, struct epoll_event *event);
|
||||
void hyper_reset_event(struct hyper_event *de);
|
||||
void hyper_event_hup(struct hyper_event *de, int efd);
|
||||
int hyper_event_read(struct hyper_event *de);
|
||||
int hyper_event_write(struct hyper_event *de);
|
||||
int hyper_event_read(struct hyper_event *dei, int efd);
|
||||
int hyper_event_write(struct hyper_event *de, int efd);
|
||||
#endif
|
||||
|
||||
+653
-344
File diff suppressed because it is too large
Load Diff
+32
-14
@@ -4,33 +4,51 @@
|
||||
#include "list.h"
|
||||
#include "event.h"
|
||||
|
||||
struct env {
|
||||
char *env;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct hyper_exec {
|
||||
struct list_head list;
|
||||
struct hyper_event e;
|
||||
char *id;
|
||||
char *pty;
|
||||
char **argv;
|
||||
int argc;
|
||||
uint64_t seq;
|
||||
struct hyper_event stdinev;
|
||||
struct hyper_event stdoutev;
|
||||
struct hyper_event stderrev;
|
||||
int pid;
|
||||
int ptyno;
|
||||
int init;
|
||||
int ptyfd;
|
||||
int stdinfd;
|
||||
int stdoutfd;
|
||||
int stderrfd;
|
||||
uint8_t close_stdin_request;
|
||||
uint8_t code;
|
||||
uint8_t exit;
|
||||
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;
|
||||
|
||||
int hyper_exec_cmd(char *json, int length);
|
||||
int hyper_release_exec(struct hyper_exec *, struct hyper_pod *);
|
||||
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);
|
||||
int hyper_run_process(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_seq(struct hyper_pod *pod, uint64_t seq);
|
||||
int hyper_send_exec_eof(int to, struct hyper_pod *pod,
|
||||
struct list_head *head, int pid,
|
||||
uint8_t code);
|
||||
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code);
|
||||
void hyper_cleanup_exec(struct hyper_pod *pod);
|
||||
|
||||
extern struct hyper_event_ops pts_ops;
|
||||
#endif
|
||||
|
||||
+71
-25
@@ -1,30 +1,43 @@
|
||||
#ifndef _DVM_H_
|
||||
#define _DVM_H_
|
||||
#ifndef _HYPER_H_
|
||||
#define _HYPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "list.h"
|
||||
#include "exec.h"
|
||||
#include "event.h"
|
||||
#include "container.h"
|
||||
#include "portmapping.h"
|
||||
|
||||
enum {
|
||||
SETDVM,
|
||||
RESERVED,
|
||||
STARTPOD,
|
||||
GETPOD,
|
||||
STOPPOD,
|
||||
DESTROYPOD,
|
||||
RESTARTCONTAINER,
|
||||
EXECCMD,
|
||||
FINISHCMD,
|
||||
CMDFINISHED,
|
||||
READY,
|
||||
ACK,
|
||||
ERROR,
|
||||
WINSIZE,
|
||||
PING,
|
||||
FINISH,
|
||||
PODFINISHED,
|
||||
NEXT,
|
||||
WRITEFILE,
|
||||
READFILE,
|
||||
NEWCONTAINER,
|
||||
KILLCONTAINER,
|
||||
ONLINECPUMEM,
|
||||
SETUPINTERFACE,
|
||||
SETUPROUTE,
|
||||
REMOVECONTAINER,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -34,48 +47,81 @@ enum {
|
||||
};
|
||||
|
||||
struct hyper_pod {
|
||||
struct hyper_container *c;
|
||||
struct hyper_interface *iface;
|
||||
struct hyper_route *rt;
|
||||
struct list_head pe_head;
|
||||
struct list_head ce_head;
|
||||
struct portmapping_white_list *portmap_white_lists;
|
||||
char **dns;
|
||||
struct list_head containers;
|
||||
struct list_head exec_head;
|
||||
char *hostname;
|
||||
char *tag;
|
||||
char *channel;
|
||||
char *share_tag;
|
||||
int init_pid;
|
||||
uint32_t c_num;
|
||||
uint32_t i_num;
|
||||
uint32_t r_num;
|
||||
uint32_t e_num;
|
||||
uint32_t d_num;
|
||||
uint32_t type;
|
||||
uint32_t code;
|
||||
/* how many containers are running */
|
||||
uint32_t remains;
|
||||
uint8_t policy;
|
||||
int efd;
|
||||
struct hyper_event sig;
|
||||
struct hyper_event ctl;
|
||||
};
|
||||
|
||||
struct portmapping_white_list {
|
||||
char **internal_networks;
|
||||
char **external_networks;
|
||||
uint32_t i_num;
|
||||
uint32_t e_num;
|
||||
};
|
||||
|
||||
struct hyper_win_size {
|
||||
char *tty;
|
||||
int row;
|
||||
int column;
|
||||
uint64_t seq;
|
||||
};
|
||||
|
||||
struct hyper_ctl {
|
||||
int efd;
|
||||
struct hyper_event sig;
|
||||
struct hyper_event tty;
|
||||
struct hyper_event chan;
|
||||
struct hyper_event ctl;
|
||||
struct hyper_reader {
|
||||
char *id;
|
||||
char *file;
|
||||
};
|
||||
|
||||
int hyper_mkdir(char *hyper_path);
|
||||
struct hyper_writter {
|
||||
char *id;
|
||||
char *file;
|
||||
uint8_t *data;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct hyper_ctl {
|
||||
int efd;
|
||||
struct hyper_event tty;
|
||||
struct hyper_event chan;
|
||||
};
|
||||
|
||||
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);
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
||||
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_ctl ctl;
|
||||
extern struct hyper_exec *global_exec;
|
||||
extern sigset_t orig_mask;
|
||||
#endif
|
||||
|
||||
+854
-666
File diff suppressed because it is too large
Load Diff
+11
-4
@@ -164,14 +164,18 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
int i;
|
||||
jsmntok_t *token;
|
||||
int count = 0;
|
||||
int num = 0;
|
||||
int out = 0;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
for (; parser->pos < len && js[parser->pos] != '\0' && !out; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{': case '[':
|
||||
case '{':
|
||||
num++;
|
||||
case '[':
|
||||
count++;
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
@@ -189,7 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}': case ']':
|
||||
case '}':
|
||||
if (--num <= 0)
|
||||
out = 1;
|
||||
case ']':
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
@@ -221,7 +228,7 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#include <termios.h>
|
||||
|
||||
#include "hyper.h"
|
||||
#include "util.h"
|
||||
#include "parse.h"
|
||||
#include "../config.h"
|
||||
|
||||
void hyper_set_be32(uint8_t *buf, uint32_t val)
|
||||
@@ -90,7 +92,7 @@ int hyper_send_type(int fd, uint32_t type)
|
||||
return hyper_send_msg(fd, type, 0, NULL);
|
||||
}
|
||||
|
||||
int hyper_get_type_block(int fd, uint32_t *type)
|
||||
int hyper_get_type(int fd, uint32_t *type)
|
||||
{
|
||||
int len = 0, size;
|
||||
uint8_t buf[8];
|
||||
@@ -111,42 +113,20 @@ int hyper_get_type_block(int fd, uint32_t *type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack)
|
||||
int hyper_send_msg_block(int fd, uint32_t type, uint32_t len, uint8_t *data)
|
||||
{
|
||||
int ret = 0, flags;
|
||||
uint32_t t;
|
||||
int ret, flags;
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
flags = hyper_setfd_block(fd);
|
||||
if (flags < 0) {
|
||||
fprintf(stderr, "get fd flag failed\n");
|
||||
fprintf(stderr, "%s fail to set fd block\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) {
|
||||
perror("set fd BLOCK failed");
|
||||
return -1;
|
||||
}
|
||||
ret = hyper_send_msg(fd, type, len, data);
|
||||
|
||||
ret = hyper_send_msg(fd, type, 0, NULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (need_ack == 0)
|
||||
goto out;
|
||||
|
||||
ret = hyper_get_type_block(fd, &t);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "can not get type\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf(stdout, "get type %" PRIu32"\n", type);
|
||||
|
||||
if (t != ACK)
|
||||
ret = -1;
|
||||
out:
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
perror("set fd BLOCK failed");
|
||||
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||
perror("restore fd flag failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -307,14 +287,17 @@ static int hyper_remove_nic(char *device)
|
||||
{
|
||||
char path[256], real[128];
|
||||
int fd;
|
||||
ssize_t size;
|
||||
|
||||
sprintf(path, "/sys/class/net/%s", device);
|
||||
|
||||
if (readlink(path, real, 128) < 0) {
|
||||
size = readlink(path, real, 128);
|
||||
if (size < 0 || size > 127) {
|
||||
perror("fail to read link directory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
real[size] = '\0';
|
||||
sprintf(path, "/sys/%s/../../../remove", real + 5);
|
||||
|
||||
fprintf(stdout, "get net sys path %s\n", path);
|
||||
@@ -676,6 +659,11 @@ static int hyper_cleanup_interface(struct rtnl_handle *rth,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't down&remove lo device */
|
||||
if (strcmp(iface->device, "lo") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hyper_down_nic(rth, iface->ifindex) < 0) {
|
||||
fprintf(stderr, "up device %d failed\n", iface->ifindex);
|
||||
return -1;
|
||||
@@ -795,3 +783,127 @@ void hyper_cleanup_network(struct hyper_pod *pod)
|
||||
pod->i_num = 0;
|
||||
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 i, fd, ret = -1;
|
||||
char buf[28];
|
||||
|
||||
if (pod->dns == NULL)
|
||||
return 0;
|
||||
|
||||
fd = open("/tmp/hyper/resolv.conf", O_CREAT| O_TRUNC| O_WRONLY, 0644);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("create /tmp/resolv.conf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < pod->d_num; i++) {
|
||||
int size = snprintf(buf, sizeof(buf), "nameserver %s\n", pod->dns[i]);
|
||||
int len = 0, l;
|
||||
|
||||
if (size < 0) {
|
||||
fprintf(stderr, "sprintf resolv.conf entry failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (len < size) {
|
||||
l = write(fd, buf + len, size - len);
|
||||
if (l < 0) {
|
||||
perror("fail to write resolv.conf");
|
||||
goto out;
|
||||
}
|
||||
len += l;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hyper_cleanup_dns(struct hyper_pod *pod)
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
for (i = 0; i < pod->d_num; i++) {
|
||||
free(pod->dns[i]);
|
||||
}
|
||||
|
||||
free(pod->dns);
|
||||
pod->dns = NULL;
|
||||
pod->d_num = 0;
|
||||
|
||||
fd = open("/tmp/hyper/resolv.conf", O_WRONLY| O_TRUNC);
|
||||
if (fd < 0) {
|
||||
perror("open /tmp/hyper/resolv.conf failed");
|
||||
return;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -47,11 +47,15 @@ uint32_t hyper_get_be32(uint8_t *buf);
|
||||
void hyper_set_be64(uint8_t *buf, uint64_t val);
|
||||
uint64_t hyper_get_be64(uint8_t *buf);
|
||||
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);
|
||||
int hyper_get_type_block(int fd, uint32_t *type);
|
||||
int hyper_setup_dns(struct hyper_pod *pod);
|
||||
void hyper_cleanup_dns(struct hyper_pod *pod);
|
||||
int hyper_get_type(int fd, uint32_t *type);
|
||||
int hyper_send_type(int fd, uint32_t type);
|
||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack);
|
||||
int hyper_send_msg(int fd, uint32_t type, uint32_t len,
|
||||
uint8_t *message);
|
||||
int hyper_send_msg(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||
int hyper_send_msg_block(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||
int hyper_send_data(int fd, uint8_t *data, uint32_t len);
|
||||
#endif
|
||||
|
||||
+1140
-202
File diff suppressed because it is too large
Load Diff
+10
-2
@@ -1,13 +1,21 @@
|
||||
#ifndef _DVM_JSON_H_
|
||||
#define _DVM_JSON_H_
|
||||
#ifndef _PARSE_H_
|
||||
#define _PARSE_H_
|
||||
|
||||
#include "hyper.h"
|
||||
#include "jsmn.h"
|
||||
#include "parson.h"
|
||||
|
||||
int hyper_parse_pod(struct hyper_pod *pod, char *json, int length);
|
||||
struct hyper_exec *hyper_parse_execcmd(char *json, int length);
|
||||
char *json_token_str(char *js, jsmntok_t *t);
|
||||
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_write_file(struct hyper_writter *writter, 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);
|
||||
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
|
||||
|
||||
+2070
File diff suppressed because it is too large
Load Diff
+223
@@ -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
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -0,0 +1,16 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/*
|
||||
* Use raw syscall for versions of glibc that don't include it. But this
|
||||
* requires kernel-headers for syscall number hint.
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_SETNS) && defined(__NR_setns)
|
||||
static inline int setns(int fd, int nstype)
|
||||
{
|
||||
errno = syscall(__NR_setns, fd, nstype);
|
||||
return errno == 0 ? 0 : -1;
|
||||
}
|
||||
#endif
|
||||
+371
-74
@@ -9,13 +9,19 @@
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "util.h"
|
||||
#include "hyper.h"
|
||||
#include "container.h"
|
||||
#include "../config.h"
|
||||
|
||||
char *read_cmdline(void)
|
||||
@@ -23,6 +29,22 @@ char *read_cmdline(void)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hyper_setup_env(struct env *envs, int num)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct env *env;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
env = &envs[i];
|
||||
if (setenv(env->env, env->value, 1) < 0) {
|
||||
perror("fail to setup env");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_list_dir(char *path)
|
||||
{
|
||||
struct dirent **list;
|
||||
@@ -39,52 +61,351 @@ int hyper_list_dir(char *path)
|
||||
for (i = 0; i < num; i++) {
|
||||
dir = list[i];
|
||||
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
||||
free(dir);
|
||||
}
|
||||
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_mkdir(char *hyper_path)
|
||||
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 *dir;
|
||||
char path[512];
|
||||
int i, num;
|
||||
|
||||
sprintf(path, "/sys/class/scsi_disk/0:0:%s/device/block/", addr);
|
||||
fprintf(stdout, "orig dev %s, scan path %s\n", *dev, path);
|
||||
|
||||
num = scandir(path, &list, NULL, NULL);
|
||||
if (num < 0) {
|
||||
perror("scan path failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dir = list[i];
|
||||
if (dir->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
||||
*dev = strdup(dir->d_name);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
free(list[i]);
|
||||
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
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;
|
||||
char *p, *path = strdup(hyper_path);
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fprintf(stdout, "create directory %s\n", path);
|
||||
if (stat(path, &st) >= 0) {
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return 0;
|
||||
goto out;
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
p = strrchr(path, '/');
|
||||
if (p == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (p != path) {
|
||||
*p = '\0';
|
||||
|
||||
if (hyper_mkdir(path) < 0)
|
||||
return -1;
|
||||
if (hyper_mkdir(path, mode) < 0)
|
||||
goto fail;
|
||||
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
if (mkdir(path, 0755) < 0 && errno != EEXIST)
|
||||
return -1;
|
||||
|
||||
fprintf(stdout, "create directory %s\n", path);
|
||||
if (mkdir(path, mode) < 0 && errno != EEXIST) {
|
||||
perror("failed to create directory");
|
||||
goto fail;
|
||||
}
|
||||
out:
|
||||
free(path);
|
||||
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
|
||||
@@ -174,8 +495,7 @@ int hyper_insmod(char *module)
|
||||
ret = 0;
|
||||
out:
|
||||
close(fd);
|
||||
if (buf)
|
||||
free(buf);
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
@@ -286,7 +606,7 @@ int hyper_setfd_block(int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return flags;
|
||||
}
|
||||
|
||||
int hyper_setfd_nonblock(int fd)
|
||||
@@ -303,10 +623,10 @@ int hyper_setfd_nonblock(int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return flags;
|
||||
}
|
||||
|
||||
void hyper_unmount_all(void)
|
||||
static void hyper_unmount_all(void)
|
||||
{
|
||||
FILE *mtab;
|
||||
struct mntent *mnt;
|
||||
@@ -346,69 +666,46 @@ void hyper_unmount_all(void)
|
||||
fprintf(stdout, ("umount %s: %s failed\n"),
|
||||
filesys, strerror(errno));
|
||||
}
|
||||
free(filesys);
|
||||
mntlist[i] = NULL;
|
||||
}
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
void hyper_kill_all(void)
|
||||
void hyper_shutdown(int error)
|
||||
{
|
||||
int npids = 0;
|
||||
int index = 0;
|
||||
int pid;
|
||||
DIR *dp;
|
||||
struct dirent *de;
|
||||
pid_t *pids = NULL;
|
||||
|
||||
dp = opendir("/proc");
|
||||
if (dp == NULL)
|
||||
return;
|
||||
|
||||
while ((de = readdir(dp)) && de != NULL) {
|
||||
if (!isdigit(de->d_name[0]))
|
||||
continue;
|
||||
pid = atoi(de->d_name);
|
||||
if (pid == 1)
|
||||
continue;
|
||||
if (index <= npids) {
|
||||
pids = realloc(pids, npids + 16384);
|
||||
if (pids == NULL)
|
||||
return;
|
||||
npids += 16384;
|
||||
}
|
||||
|
||||
pids[index++] = pid;
|
||||
}
|
||||
|
||||
fprintf(stdout, "Sending SIGTERM\n");
|
||||
|
||||
for (--index; index >= 0; --index) {
|
||||
fprintf(stdout, "kill process %d\n", pids[index]);
|
||||
kill(pids[index], SIGTERM);
|
||||
}
|
||||
|
||||
free(pids);
|
||||
closedir(dp);
|
||||
}
|
||||
|
||||
int hyper_send_finish(struct hyper_pod *pod)
|
||||
{
|
||||
int i;
|
||||
uint8_t *data = calloc(pod->c_num, 4);
|
||||
|
||||
for (i = 0; i < pod->c_num; i++)
|
||||
hyper_set_be32(data + (i * 4), pod->c[i].exec.code);
|
||||
|
||||
return hyper_send_msg(ctl.chan.fd, FINISH, pod->c_num * 4, data);
|
||||
}
|
||||
|
||||
void hyper_shutdown(struct hyper_pod *pod)
|
||||
{
|
||||
hyper_send_finish(pod);
|
||||
|
||||
//hyper_kill_all();
|
||||
|
||||
hyper_send_msg_block(ctl.chan.fd, error?ERROR:ACK, 0, NULL);
|
||||
hyper_unmount_all();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
+20
-5
@@ -2,27 +2,42 @@
|
||||
#define _UTIL_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include "../config.h"
|
||||
|
||||
struct hyper_pod;
|
||||
struct env;
|
||||
|
||||
#ifdef WITH_DEBUG
|
||||
#define dprintf(fmt, ...) \
|
||||
fprintf(stdout, fmt, ##_VA_ARGS__)
|
||||
fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dprintf(fmr, ...)
|
||||
#endif
|
||||
|
||||
char *read_cmdline(void);
|
||||
int hyper_setup_env(struct env *envs, int num);
|
||||
int hyper_find_sd(char *addr, char **dev);
|
||||
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_serial_dev(char *tty);
|
||||
int hyper_setfd_cloexec(int fd);
|
||||
int hyper_setfd_block(int fd);
|
||||
int hyper_setfd_nonblock(int fd);
|
||||
void hyper_shutdown(struct hyper_pod *pod);
|
||||
int hyper_send_finish(struct hyper_pod *pod);
|
||||
void hyper_unmount_all(void);
|
||||
int hyper_socketpair(int domain, int type, int protocol, int sv[2]);
|
||||
void hyper_shutdown(int ack);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user