mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-09-06 13:41:44 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b055f07cbb | ||
|
|
a615be817c | ||
|
|
4fc7dddb53 | ||
|
|
256c491948 | ||
|
|
9844779c4e | ||
|
|
b6eff45cc4 | ||
|
|
6d75e8cc93 | ||
|
|
fcc968a004 | ||
|
|
bbb111ea6d | ||
|
|
88f445ce34 | ||
|
|
3747b03b70 | ||
|
|
b1d90cf796 | ||
|
|
0470974773 | ||
|
|
66bcaedf2a | ||
|
|
6b4a925945 | ||
|
|
ca80a07ede | ||
|
|
467d776b15 | ||
|
|
3293eaa34b | ||
|
|
18235fc443 | ||
|
|
9a406cc3dd | ||
|
|
d39a4a03f1 | ||
|
|
2878ec5890 | ||
|
|
b900783a3b | ||
|
|
9132f7549d | ||
|
|
232afc9538 | ||
|
|
3d0f9b1692 | ||
|
|
6afbb02017 | ||
|
|
7e64971357 | ||
|
|
eb59290a59 | ||
|
|
dc46e20caa | ||
|
|
8fdd03c635 | ||
|
|
807ef53908 | ||
|
|
1acd0280e8 | ||
|
|
2e3bc177ea | ||
|
|
ec20f8ab0a | ||
|
|
648d99fa64 | ||
|
|
2621a406cf | ||
|
|
72a049a72d | ||
|
|
1fda991fee | ||
|
|
9077cf47b3 | ||
|
|
ac4d6d8fc7 | ||
|
|
b232c8fcc9 | ||
|
|
cb680e280d | ||
|
|
7401981c22 | ||
|
|
83c3c1d424 | ||
|
|
9cd968e2d2 | ||
|
|
290217c87a | ||
|
|
39c027e58c | ||
|
|
22cfaea4d2 | ||
|
|
e3704f66ba | ||
|
|
8ac18bf650 | ||
|
|
d63f716523 | ||
|
|
1973768704 | ||
|
|
4011640b08 | ||
|
|
db6f286244 | ||
|
|
b2e7a0f631 | ||
|
|
f4ad330a75 | ||
|
|
54f5362a03 | ||
|
|
45967cc8b8 | ||
|
|
728d02983e | ||
|
|
4e830d77b4 | ||
|
|
2a669f0558 | ||
|
|
5ed9195bf8 | ||
|
|
064879ff0a | ||
|
|
2360c4dc3f | ||
|
|
da72799c96 | ||
|
|
56198c3acd | ||
|
|
a07cabf2d0 | ||
|
|
440e14cde4 | ||
|
|
5b1b29593e | ||
|
|
519db047fb | ||
|
|
504218c41f | ||
|
|
c0e8d92d9a | ||
|
|
be7654b416 | ||
|
|
1cf932a784 | ||
|
|
5c30a49c27 | ||
|
|
4b662dd4fa | ||
|
|
13a58d6531 | ||
|
|
ecf00fc578 | ||
|
|
819f639334 | ||
|
|
cdc84ecb4b | ||
|
|
9d7a6c0a0f | ||
|
|
d9e871409e | ||
|
|
bb5c2c5744 | ||
|
|
2f2be98cff | ||
|
|
28ea806216 | ||
|
|
8c45a5d6fe | ||
|
|
98262e7e50 | ||
|
|
ff845ee371 | ||
|
|
6224d6b779 | ||
|
|
2fb3ad7474 | ||
|
|
82c1ecd25a | ||
|
|
b46bc34498 | ||
|
|
0c5335b8d5 | ||
|
|
dca1bd6aaa | ||
|
|
c4f06c3fcd | ||
|
|
92fc1d65a5 | ||
|
|
e0bc511a97 | ||
|
|
46fd62cafd | ||
|
|
41438d40d6 | ||
|
|
7294253548 | ||
|
|
41366ae88a | ||
|
|
5edb81f783 | ||
|
|
eea9702389 | ||
|
|
7acbc5e288 | ||
|
|
34ec350357 | ||
|
|
b58b03874d | ||
|
|
02b777058d | ||
|
|
17f9f7b4cf | ||
|
|
4fa99f7a5b | ||
|
|
6efb8d2638 | ||
|
|
e2b79425f1 | ||
|
|
21cb97d970 | ||
|
|
f06259b0b9 | ||
|
|
70dd9f1447 | ||
|
|
8b674e78f5 | ||
|
|
de59d91bc2 | ||
|
|
6824ff3d2e | ||
|
|
ffd28a721c | ||
|
|
6f73ec97e3 | ||
|
|
f01a9f4081 | ||
|
|
79d066d847 | ||
|
|
9089ec3f25 | ||
|
|
6e8bc85878 | ||
|
|
4c0887f131 | ||
|
|
3d942a45bb | ||
|
|
83223f6832 | ||
|
|
a2202183fb | ||
|
|
37856283d5 | ||
|
|
bb7ebdaadd | ||
|
|
fe5c9a9d9c | ||
|
|
62ef95ba93 | ||
|
|
d8fb6c1af3 | ||
|
|
2ccac3fa9c | ||
|
|
52c87dc016 | ||
|
|
f359cb9468 | ||
|
|
3de74e927c | ||
|
|
7b54d5c9da | ||
|
|
1e4711d898 | ||
|
|
cb71f43ed1 | ||
|
|
c72276b004 | ||
|
|
5735f9f674 | ||
|
|
de0c2c97e4 | ||
|
|
8a86dd1f51 | ||
|
|
5ba9b2550d | ||
|
|
da986b4a3a | ||
|
|
5b21370efd | ||
|
|
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 | ||
|
|
6680827faf | ||
|
|
7699c38b99 |
@@ -7,12 +7,16 @@
|
|||||||
.#*
|
.#*
|
||||||
.git
|
.git
|
||||||
.deps
|
.deps
|
||||||
|
TAGS
|
||||||
|
tags
|
||||||
init
|
init
|
||||||
build/hyper_daemon
|
build/hyper_daemon
|
||||||
build/hyper-initrd.img
|
build/hyper-initrd.img
|
||||||
|
build/cbfs.rom
|
||||||
build/root/*
|
build/root/*
|
||||||
build/*iso
|
build/*iso
|
||||||
build/daemon
|
build/daemon
|
||||||
|
build/kernel_config.old
|
||||||
build/.*
|
build/.*
|
||||||
src/.*
|
src/.*
|
||||||
Makefile
|
Makefile
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
sudo: required
|
||||||
|
dist: trusty
|
||||||
|
|
||||||
|
language: c
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- go: 1.7
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- sudo apt-get update -qq
|
||||||
|
- sudo apt-get install -y autoconf automake pkg-config libdevmapper-dev libsqlite3-dev libvirt-dev qemu libvirt-bin -qq
|
||||||
|
- cd `mktemp -d`
|
||||||
|
- wget https://git.fedorahosted.org/cgit/lvm2.git/snapshot/lvm2-2_02_131.tar.xz
|
||||||
|
- tar xf lvm2-2_02_131.tar.xz
|
||||||
|
- cd lvm2-2_02_131
|
||||||
|
- ./configure && make device-mapper && sudo make install
|
||||||
|
|
||||||
|
script:
|
||||||
|
- cd ${TRAVIS_BUILD_DIR}
|
||||||
|
- ./autogen.sh
|
||||||
|
- ./configure
|
||||||
|
- make
|
||||||
|
- hack/test-cmd.sh
|
||||||
@@ -4,3 +4,5 @@ initrd-local:
|
|||||||
@echo finish make initrd
|
@echo finish make initrd
|
||||||
cbfs-local:
|
cbfs-local:
|
||||||
@echo finish make cbfs
|
@echo finish make cbfs
|
||||||
|
kernel-local:
|
||||||
|
@echo finish make kernel
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
# 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
|
## 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
|
> ./autogen.sh
|
||||||
> ./configure
|
> ./configure
|
||||||
> make
|
> 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 run hyperstart with 64-bit ARM architecture, please reconfigure with flag --with-aarch64,
|
||||||
|
|
||||||
|
> ./configure --with-aarch64
|
||||||
|
> make
|
||||||
|
|
||||||
|
If you want to get the boot disk file for VirtualBox, please reconfigure with flag --with-vbox,
|
||||||
|
|
||||||
> ./configure --with-vbox
|
> ./configure --with-vbox
|
||||||
> make
|
> 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.
|
bring you to the hyper world.
|
||||||
|
|||||||
+5
-5
@@ -8,34 +8,34 @@ DIE=0
|
|||||||
|
|
||||||
test -f src/init.c || {
|
test -f src/init.c || {
|
||||||
echo
|
echo
|
||||||
echo "You must run this script in the top-level hyperint drectory."
|
echo "You must run this script in the top-level hyperstart drectory."
|
||||||
echo
|
echo
|
||||||
DIE=1
|
DIE=1
|
||||||
}
|
}
|
||||||
|
|
||||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
echo
|
echo
|
||||||
echo "You must have autoconf installed to generate the hyperinit."
|
echo "You must have autoconf installed to generate the hyperstart."
|
||||||
echo
|
echo
|
||||||
DIE=1
|
DIE=1
|
||||||
}
|
}
|
||||||
|
|
||||||
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
|
(autoheader --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
echo
|
echo
|
||||||
echo "You must have autoheader installed to generate the hypernit."
|
echo "You must have autoheader installed to generate the hyperstart."
|
||||||
echo
|
echo
|
||||||
DIE=1
|
DIE=1
|
||||||
}
|
}
|
||||||
|
|
||||||
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
(automake --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
echo
|
echo
|
||||||
echo "You must have automake installed to generate the hypernit."
|
echo "You must have automake installed to generate the hyperstart."
|
||||||
echo
|
echo
|
||||||
DIE=1
|
DIE=1
|
||||||
}
|
}
|
||||||
(autoreconf --version) < /dev/null > /dev/null 2>&1 || {
|
(autoreconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||||
echo
|
echo
|
||||||
echo "You must have autoreconf installed to generate the hypernit."
|
echo "You must have autoreconf installed to generate the hyperstart."
|
||||||
echo
|
echo
|
||||||
DIE=1
|
DIE=1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -4,9 +4,21 @@ if WITH_VBOX
|
|||||||
initrd-local:
|
initrd-local:
|
||||||
bash ./make-initrd.sh vbox
|
bash ./make-initrd.sh vbox
|
||||||
else
|
else
|
||||||
|
if WITH_AARCH64
|
||||||
|
initrd-local:
|
||||||
|
bash ./make-initrd.sh aarch64
|
||||||
|
else
|
||||||
initrd-local:
|
initrd-local:
|
||||||
bash ./make-initrd.sh
|
bash ./make-initrd.sh
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
cbfs-local:
|
cbfs-local:
|
||||||
bash ./make-initrd.sh cbfs
|
bash ./make-initrd.sh cbfs
|
||||||
|
|
||||||
|
kernel-local:
|
||||||
|
hyperctl build -t hyperstart-dev:latest .
|
||||||
|
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/kernel >kernel.new && mv -f kernel.new kernel
|
||||||
|
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/modules.tar >modules.tar
|
||||||
|
mv kernel_config kernel_config.old
|
||||||
|
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/kernel_config >kernel_config
|
||||||
|
|||||||
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
+916
-215
File diff suppressed because it is too large
Load Diff
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.
+43
-10
@@ -1,18 +1,50 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
rm -rf root
|
rm -rf /tmp/hyperstart-rootfs
|
||||||
mkdir root
|
mkdir -p /tmp/hyperstart-rootfs/lib \
|
||||||
|
/tmp/hyperstart-rootfs/lib64 \
|
||||||
|
/tmp/hyperstart-rootfs/lib/modules
|
||||||
|
|
||||||
cp ../src/init ./root
|
mkdir -m 0755 -p /tmp/hyperstart-rootfs/dev \
|
||||||
|
/tmp/hyperstart-rootfs/sys \
|
||||||
|
/tmp/hyperstart-rootfs/sbin \
|
||||||
|
/tmp/hyperstart-rootfs/bin \
|
||||||
|
/tmp/hyperstart-rootfs/proc
|
||||||
|
|
||||||
ldd ./root/init | while read line
|
cp ../src/init /tmp/hyperstart-rootfs
|
||||||
|
cp busybox /tmp/hyperstart-rootfs
|
||||||
|
cp iptables /tmp/hyperstart-rootfs
|
||||||
|
cp libm.so.6 /tmp/hyperstart-rootfs/lib64/
|
||||||
|
|
||||||
|
if [ "$1"x = "aarch64"x ]; then
|
||||||
|
echo "build hyperstart for aarch64"
|
||||||
|
tar -xf modules_aarch64.tar -C /tmp/hyperstart-rootfs/lib/modules
|
||||||
|
else
|
||||||
|
tar -xf modules.tar -C /tmp/hyperstart-rootfs/lib/modules
|
||||||
|
fi
|
||||||
|
|
||||||
|
# create symlinks to busybox and iptables
|
||||||
|
BUSYBOX_BINARIES=(/bin/sh /bin/tar /bin/hwclock /sbin/modprobe /sbin/depmod)
|
||||||
|
for bin in ${BUSYBOX_BINARIES[@]}
|
||||||
|
do
|
||||||
|
mkdir -p /tmp/hyperstart-rootfs/`dirname ${bin}`
|
||||||
|
ln -sf /busybox /tmp/hyperstart-rootfs/${bin}
|
||||||
|
done
|
||||||
|
IPTABLES_BINARIES=(/sbin/iptables /sbin/iptables-restore /sbin/iptables-save)
|
||||||
|
for bin in ${IPTABLES_BINARIES[@]}
|
||||||
|
do
|
||||||
|
mkdir -p /tmp/hyperstart-rootfs/`dirname ${bin}`
|
||||||
|
ln -sf /iptables /tmp/hyperstart-rootfs/${bin}
|
||||||
|
done
|
||||||
|
|
||||||
|
ldd /tmp/hyperstart-rootfs/init | while read line
|
||||||
do
|
do
|
||||||
arr=(${line// / })
|
arr=(${line// / })
|
||||||
|
|
||||||
for lib in ${arr[@]}
|
for lib in ${arr[@]}
|
||||||
do
|
do
|
||||||
if [ "${lib:0:1}" = "/" ]; then
|
if [ "${lib:0:1}" = "/" ]; then
|
||||||
dir=root`dirname $lib`
|
dir=/tmp/hyperstart-rootfs`dirname $lib`
|
||||||
mkdir -p "${dir}"
|
mkdir -p "${dir}"
|
||||||
cp -f $lib $dir
|
cp -f $lib $dir
|
||||||
fi
|
fi
|
||||||
@@ -21,13 +53,12 @@ done
|
|||||||
|
|
||||||
if [ "$1"x = "vbox"x ]; then
|
if [ "$1"x = "vbox"x ]; then
|
||||||
echo "build initrd for vbox"
|
echo "build initrd for vbox"
|
||||||
cp ./vbox/driver/* ./root
|
cp ./vbox/driver/* /tmp/hyperstart-rootfs
|
||||||
fi
|
fi
|
||||||
|
|
||||||
cd ./root && find . | cpio -H newc -o | gzip -9 > ../hyper-initrd.img
|
( cd /tmp/hyperstart-rootfs && find . | cpio -H newc -o | gzip -9 ) > ./hyper-initrd.img
|
||||||
|
|
||||||
cd ../
|
rm -rf /tmp/hyperstart-rootfs
|
||||||
rm -rf ./root
|
|
||||||
|
|
||||||
if [ "$1"x = "cbfs"x ]; then
|
if [ "$1"x = "cbfs"x ]; then
|
||||||
echo "build cbfs"
|
echo "build cbfs"
|
||||||
@@ -36,9 +67,11 @@ if [ "$1"x = "cbfs"x ]; then
|
|||||||
|
|
||||||
mkdir .cbfs
|
mkdir .cbfs
|
||||||
dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1
|
dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1
|
||||||
cbfstool .cbfs/cbfs.rom create -s 4096k -B .cbfs/boot.bin -m x86 0x1000
|
cbfstool .cbfs/cbfs.rom create -s 8128k -B .cbfs/boot.bin -m x86 0x1000
|
||||||
cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw
|
cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw
|
||||||
cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw
|
cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw
|
||||||
|
echo 'console=ttyS0 panic=1 no_timer_check' > .cbfs/cmdline
|
||||||
|
cbfstool .cbfs/cbfs.rom add -f .cbfs/cmdline -n cmdline -t raw
|
||||||
cp .cbfs/cbfs.rom ./
|
cp .cbfs/cbfs.rom ./
|
||||||
rm -rf .cbfs
|
rm -rf .cbfs
|
||||||
exit 0
|
exit 0
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
+15
-2
@@ -2,9 +2,9 @@
|
|||||||
# Process this file with autoconf to produce a configure script.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([hyperstart], [0.2], [www.hyper.sh])
|
AC_INIT([hyperstart], [0.6.2], [www.hyper.sh])
|
||||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||||
AM_EXTRA_RECURSIVE_TARGETS([initrd cbfs])
|
AM_EXTRA_RECURSIVE_TARGETS([initrd cbfs kernel])
|
||||||
AC_CONFIG_SRCDIR([src/init.c])
|
AC_CONFIG_SRCDIR([src/init.c])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
@@ -32,11 +32,23 @@ AC_TYPE_UINT8_T
|
|||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_FUNC_FORK
|
AC_FUNC_FORK
|
||||||
AC_CHECK_FUNCS([dup2 memmove memset mkdir setenv socket strchr strdup strrchr strtoul], [fail=0], [fail=1])
|
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
|
if test "$fail" = "1" ; then
|
||||||
AC_MSG_ERROR(Unable to find necessary functions)
|
AC_MSG_ERROR(Unable to find necessary functions)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
AC_ARG_WITH([aarch64],
|
||||||
|
[AS_HELP_STRING([--with-aarch64],
|
||||||
|
[run hyperstart with 64-bit ARM architecture])],
|
||||||
|
[],[with_aarch64=no])
|
||||||
|
|
||||||
|
if test "x$with_aarch64" != "xno" ; then
|
||||||
|
AC_DEFINE_UNQUOTED([WITH_AARCH64], 1, [run hyperstart with 64-bit ARM architecture])
|
||||||
|
fi
|
||||||
|
|
||||||
|
AM_CONDITIONAL([WITH_AARCH64], [test "x$with_aarch64" != "xno"])
|
||||||
|
|
||||||
AC_ARG_WITH([vbox],
|
AC_ARG_WITH([vbox],
|
||||||
[AS_HELP_STRING([--with-vbox],
|
[AS_HELP_STRING([--with-vbox],
|
||||||
[run hyperstart on Virtualbox])],
|
[run hyperstart on Virtualbox])],
|
||||||
@@ -60,6 +72,7 @@ AC_MSG_RESULT([
|
|||||||
prefix: ${prefix}
|
prefix: ${prefix}
|
||||||
|
|
||||||
with-vbox: ${with_vbox}
|
with-vbox: ${with_vbox}
|
||||||
|
with-aarch64: ${with_aarch64}
|
||||||
|
|
||||||
compiler: ${CC}
|
compiler: ${CC}
|
||||||
cflags: ${CFLAGS}
|
cflags: ${CFLAGS}
|
||||||
|
|||||||
Executable
+22
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
set -o nounset
|
||||||
|
set -o pipefail
|
||||||
|
|
||||||
|
###########################
|
||||||
|
# test hyperstart from hyper
|
||||||
|
|
||||||
|
export HYPER_RUNTIME=/var/lib/hyper
|
||||||
|
sudo mkdir -p ${HYPER_RUNTIME}
|
||||||
|
sudo cp build/kernel ${HYPER_RUNTIME}/kernel
|
||||||
|
sudo cp build/hyper-initrd.img ${HYPER_RUNTIME}/hyper-initrd.img
|
||||||
|
|
||||||
|
mkdir -p ${GOPATH}/src/github.com/hyperhq
|
||||||
|
git clone https://github.com/hyperhq/hyperd.git ${GOPATH}/src/github.com/hyperhq/hyperd
|
||||||
|
cd ${GOPATH}/src/github.com/hyperhq/hyperd
|
||||||
|
./autogen.sh
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
hack/test-cmd.sh
|
||||||
|
|
||||||
+2
-2
@@ -1,3 +1,3 @@
|
|||||||
AM_CFLAGS = -Wall
|
AM_CFLAGS = -Wall -Werror
|
||||||
bin_PROGRAMS=init
|
bin_PROGRAMS=init
|
||||||
init_SOURCES=init.c jsmn.c net.c util.c parse.c container.c exec.c event.c
|
init_SOURCES=init.c jsmn.c net.c util.c parse.c parson.c container.c exec.c event.c portmapping.c
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#ifndef _HYPERSTART_API_H_
|
||||||
|
#define _HYPERSTART_API_H_
|
||||||
|
|
||||||
|
#define APIVERSION 4242
|
||||||
|
|
||||||
|
// control command id
|
||||||
|
enum {
|
||||||
|
GETVERSION,
|
||||||
|
STARTPOD,
|
||||||
|
GETPOD,
|
||||||
|
STOPPOD_DEPRECATED,
|
||||||
|
DESTROYPOD,
|
||||||
|
RESTARTCONTAINER,
|
||||||
|
EXECCMD,
|
||||||
|
CMDFINISHED,
|
||||||
|
READY,
|
||||||
|
ACK,
|
||||||
|
ERROR,
|
||||||
|
WINSIZE,
|
||||||
|
PING,
|
||||||
|
PODFINISHED,
|
||||||
|
NEXT,
|
||||||
|
WRITEFILE,
|
||||||
|
READFILE,
|
||||||
|
NEWCONTAINER,
|
||||||
|
KILLCONTAINER,
|
||||||
|
ONLINECPUMEM,
|
||||||
|
SETUPINTERFACE,
|
||||||
|
SETUPROUTE,
|
||||||
|
REMOVECONTAINER,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* control message format
|
||||||
|
* | ctrl id | length | payload (length-8) |
|
||||||
|
* | . . . . | . . . . | . . . . . . . . . . . . |
|
||||||
|
* 0 4 8 length
|
||||||
|
*/
|
||||||
|
#define CONTROL_HEADER_SIZE 8
|
||||||
|
#define CONTROL_HEADER_LENGTH_OFFSET 4
|
||||||
|
|
||||||
|
/*
|
||||||
|
* stream message format
|
||||||
|
* | stream sequence | length | payload (length-12) |
|
||||||
|
* | . . . . . . . . | . . . . | . . . . . . . . . . . . |
|
||||||
|
* 0 8 12 length
|
||||||
|
*/
|
||||||
|
#define STREAM_HEADER_SIZE 12
|
||||||
|
#define STREAM_HEADER_LENGTH_OFFSET 8
|
||||||
|
|
||||||
|
#endif /* _HYPERSTART_API_H_ */
|
||||||
+527
-265
@@ -7,6 +7,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <sys/utsname.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
@@ -16,18 +17,79 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "hyper.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 stat st;
|
||||||
struct env *env;
|
|
||||||
|
|
||||||
for (i = 0; i < container->envs_num; i++) {
|
fprintf(stdout, "populate volumes from %s to %s\n", src, dest);
|
||||||
env = &container->envs[i];
|
/* 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 directory\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 directory %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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -38,127 +100,113 @@ static int container_setup_volume(struct hyper_container *container)
|
|||||||
struct volume *vol;
|
struct volume *vol;
|
||||||
|
|
||||||
for (i = 0; i < container->vols_num; i++) {
|
for (i = 0; i < container->vols_num; i++) {
|
||||||
|
char volume[512];
|
||||||
|
char mountpoint[512];
|
||||||
|
char *options = NULL;
|
||||||
|
const char *filevolume = NULL;
|
||||||
vol = &container->vols[i];
|
vol = &container->vols[i];
|
||||||
|
|
||||||
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(path, "/tmp/%s", vol->mountpoint);
|
||||||
|
sprintf(mountpoint, "./%s", vol->mountpoint);
|
||||||
|
|
||||||
fprintf(stdout, "mount %s to %s, tmp path %s\n",
|
fprintf(stdout, "mount %s to %s, tmp path %s\n",
|
||||||
dev, vol->mountpoint, path);
|
dev, vol->mountpoint, path);
|
||||||
|
|
||||||
if (hyper_mkdir(path) < 0 || hyper_mkdir(vol->mountpoint) < 0) {
|
if (hyper_mkdir(path, 0755) < 0) {
|
||||||
perror("create volume dir failed");
|
perror("create volume dir failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount(dev, path, vol->fstype, 0, NULL) < 0) {
|
if (!strncmp(vol->fstype, "xfs", strlen("xfs")))
|
||||||
perror("mount volume device faled");
|
options = "nouuid";
|
||||||
|
|
||||||
|
if (mount(dev, path, vol->fstype, 0, options) < 0) {
|
||||||
|
perror("mount volume device failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) {
|
sprintf(volume, "/%s/_data", path);
|
||||||
perror("mount volume device faled");
|
if (container_check_file_volume(volume, &filevolume) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (filevolume == NULL) {
|
||||||
|
if (hyper_mkdir(mountpoint, 0755) < 0) {
|
||||||
|
perror("create volume dir failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (vol->docker) {
|
||||||
|
if (container->initialize &&
|
||||||
|
(container_populate_volume(mountpoint, volume) < 0)) {
|
||||||
|
fprintf(stderr, "fail to populate volume %s\n", mountpoint);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else if (hyper_mkdir(volume, 0777) < 0) {
|
||||||
|
/* First time mounting an empty volume */
|
||||||
|
perror("create _data dir failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
hyper_filize(mountpoint);
|
||||||
|
if (hyper_create_file(mountpoint) < 0) {
|
||||||
|
perror("create volume file failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
sprintf(volume, "/%s/_data/%s", path, filevolume);
|
||||||
|
/* 0777 so that any user can read/write the new file volume */
|
||||||
|
if (chmod(volume, 0777) < 0) {
|
||||||
|
fprintf(stderr, "fail to chmod directory %s\n", volume);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mount(volume, mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||||
|
perror("mount volume device failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vol->readonly &&
|
if (vol->readonly &&
|
||||||
mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
mount(volume, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
||||||
perror("mount fsmap faled");
|
perror("mount fsmap failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
umount(path);
|
umount(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void container_unmount_oldroot(char *path)
|
|
||||||
{
|
|
||||||
FILE *mtab;
|
|
||||||
struct mntent *mnt;
|
|
||||||
char *mntlist[128];
|
|
||||||
int i;
|
|
||||||
int n = 0;
|
|
||||||
char *filesys;
|
|
||||||
|
|
||||||
mtab = setmntent("/proc/mounts", "r");
|
|
||||||
if (mtab == NULL) {
|
|
||||||
fprintf(stderr, "cannot open /proc/mount");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (n < 128 && (mnt = getmntent(mtab))) {
|
|
||||||
if (strncmp(mnt->mnt_dir, path, strlen(path)))
|
|
||||||
continue;
|
|
||||||
mntlist[n++] = strdup(mnt->mnt_dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
endmntent(mtab);
|
|
||||||
|
|
||||||
for (i = n - 1; i >= 0; i--) {
|
|
||||||
filesys = mntlist[i];
|
|
||||||
fprintf(stdout, "umount %s\n", filesys);
|
|
||||||
if (umount(mntlist[i]) < 0 && umount2(mntlist[i],
|
|
||||||
MNT_DETACH) < 0) {
|
|
||||||
fprintf(stdout, "umount %s: %s failed\n",
|
|
||||||
filesys, strerror(errno));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static int container_setup_mount(struct hyper_container *container)
|
|
||||||
{
|
|
||||||
int i, fd;
|
|
||||||
char src[512];
|
|
||||||
struct fsmap *map;
|
|
||||||
|
|
||||||
hyper_mkdir("/proc");
|
|
||||||
hyper_mkdir("/sys");
|
|
||||||
hyper_mkdir("/dev");
|
|
||||||
|
|
||||||
if (mount("proc", "/proc", "proc", 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++) {
|
for (i = 0; i < container->maps_num; i++) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
char *src, path[512], volume[512];
|
||||||
|
struct fsmap *map = &container->maps[i];
|
||||||
|
char mountpoint[512];
|
||||||
|
|
||||||
map = &container->maps[i];
|
sprintf(path, "%s/%s", SHARED_DIR, map->source);
|
||||||
|
sprintf(mountpoint, "./%s", map->path);
|
||||||
sprintf(src, "/.oldroot/tmp/hyper/shared/%s", map->source);
|
fprintf(stdout, "mount %s to %s\n", path, mountpoint);
|
||||||
fprintf(stdout, "mount %s to %s\n", src, map->path);
|
|
||||||
|
|
||||||
|
src = path;
|
||||||
stat(src, &st);
|
stat(src, &st);
|
||||||
|
|
||||||
if (st.st_mode & S_IFDIR) {
|
if (st.st_mode & S_IFDIR) {
|
||||||
if (hyper_mkdir(map->path) < 0) {
|
if (hyper_mkdir(mountpoint, 0755) < 0) {
|
||||||
perror("create map dir failed");
|
perror("create map dir failed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
if (map->docker) {
|
||||||
|
/* converted from volume */
|
||||||
|
sprintf(volume, "%s/_data", path);
|
||||||
|
src = volume;
|
||||||
|
if (container->initialize &&
|
||||||
|
(container_populate_volume(mountpoint, volume) < 0)) {
|
||||||
|
fprintf(stderr, "fail to populate volume %s\n", mountpoint);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
fd = open(map->path, O_CREAT|O_WRONLY, 0755);
|
int fd = open(mountpoint, O_CREAT|O_WRONLY, 0755);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("create map file failed");
|
perror("create map file failed");
|
||||||
continue;
|
continue;
|
||||||
@@ -166,16 +214,232 @@ static int container_setup_mount(struct hyper_container *container)
|
|||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount(src, map->path, NULL, MS_BIND, NULL) < 0) {
|
if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||||
perror("mount fsmap faled");
|
perror("mount fsmap failed");
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (map->readonly == 0)
|
if (map->readonly == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (mount(src, map->path, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
if (mount(src, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
||||||
perror("mount fsmap faled");
|
perror("mount fsmap failed");
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (symlink("/dev/pts/ptmx", "./dev/ptmx") < 0) {
|
||||||
|
perror("link /dev/pts/ptmx to /dev/ptmx failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* all containers share the same devtmpfs, so we need to ignore the errno EEXIST */
|
||||||
|
if ((symlink("/proc/self/fd", "./dev/fd") < 0 && errno != EEXIST) ||
|
||||||
|
(symlink("/proc/self/fd/0", "./dev/stdin") < 0 && errno != EEXIST) ||
|
||||||
|
(symlink("/proc/self/fd/1", "./dev/stdout") < 0 && errno != EEXIST) ||
|
||||||
|
(symlink("/proc/self/fd/2", "./dev/stderr") < 0 && errno != EEXIST)) {
|
||||||
|
perror("failed to symlink for /dev/fd, /dev/stdin, /dev/stdout or /dev/stderr");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
return 0;
|
||||||
@@ -183,19 +447,14 @@ static int container_setup_mount(struct hyper_container *container)
|
|||||||
|
|
||||||
static int container_setup_workdir(struct hyper_container *container)
|
static int container_setup_workdir(struct hyper_container *container)
|
||||||
{
|
{
|
||||||
if (container->workdir && chdir(container->workdir) < 0) {
|
if (container->initialize) {
|
||||||
perror("change work directory failed");
|
// create workdir
|
||||||
return -1;
|
return hyper_mkdir(container->exec.workdir, 0755);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int container_setup_tty(int fd, struct hyper_container *container)
|
|
||||||
{
|
|
||||||
return hyper_dup_exec_tty(fd, &container->exec);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int hyper_rescan_scsi(void)
|
static int hyper_rescan_scsi(void)
|
||||||
{
|
{
|
||||||
struct dirent **list;
|
struct dirent **list;
|
||||||
@@ -205,7 +464,7 @@ static int hyper_rescan_scsi(void)
|
|||||||
|
|
||||||
num = scandir("/sys/class/scsi_host/", &list, NULL, NULL);
|
num = scandir("/sys/class/scsi_host/", &list, NULL, NULL);
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
perror("scan /sys/calss/virtio-ports/ failed");
|
perror("scan /sys/class/scsi_host/ failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,31 +502,38 @@ static int hyper_rescan_scsi(void)
|
|||||||
|
|
||||||
struct hyper_container_arg {
|
struct hyper_container_arg {
|
||||||
struct hyper_container *c;
|
struct hyper_container *c;
|
||||||
|
struct hyper_pod *pod;
|
||||||
int pipe[2];
|
int pipe[2];
|
||||||
|
int pipens[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
static int hyper_container_init(void *data)
|
static int hyper_setup_container_rootfs(void *data)
|
||||||
{
|
{
|
||||||
struct hyper_container_arg *arg = data;
|
struct hyper_container_arg *arg = data;
|
||||||
struct hyper_container *container = arg->c;
|
struct hyper_container *container = arg->c;
|
||||||
char root[512], oldroot[512];
|
char root[512], rootfs[512];
|
||||||
|
int setup_dns;
|
||||||
|
uint32_t type;
|
||||||
|
|
||||||
fprintf(stdout, "%s in\n", __func__);
|
/* wait for ns-opened ready message */
|
||||||
if (container->exec.argv == NULL) {
|
if (hyper_get_type(arg->pipens[0], &type) < 0 || type != READY) {
|
||||||
fprintf(stdout, "no cmd!\n");
|
fprintf(stderr, "wait for /proc/self/ns/mnt opened failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hyper_rescan_scsi() < 0) {
|
if (hyper_enter_sandbox(arg->pod, -1) < 0) {
|
||||||
|
perror("enter sandbox failed");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* To create files/directories accessible for all users. */
|
||||||
|
umask(0);
|
||||||
|
|
||||||
|
if (container->fstype && hyper_rescan_scsi() < 0) {
|
||||||
fprintf(stdout, "rescan scsi failed\n");
|
fprintf(stdout, "rescan scsi failed\n");
|
||||||
goto fail;
|
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) {
|
if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
|
||||||
perror("mount SLAVE failed");
|
perror("mount SLAVE failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
@@ -279,8 +545,8 @@ static int hyper_container_init(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sprintf(root, "/tmp/hyper/%s/root/", container->id);
|
sprintf(root, "/tmp/hyper/%s/root/", container->id);
|
||||||
if (hyper_mkdir(root) < 0) {
|
if (hyper_mkdir(root, 0755) < 0) {
|
||||||
perror("make root directroy failed");
|
perror("make root directory failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,18 +554,28 @@ static int hyper_container_init(void *data)
|
|||||||
|
|
||||||
if (container->fstype) {
|
if (container->fstype) {
|
||||||
char dev[128];
|
char dev[128];
|
||||||
|
char *options = NULL;
|
||||||
|
|
||||||
|
if (container->scsiaddr) {
|
||||||
|
free(container->image);
|
||||||
|
container->image = NULL;
|
||||||
|
hyper_find_sd(container->scsiaddr, &container->image);
|
||||||
|
}
|
||||||
|
|
||||||
sprintf(dev, "/dev/%s", container->image);
|
sprintf(dev, "/dev/%s", container->image);
|
||||||
fprintf(stdout, "device %s\n", dev);
|
fprintf(stdout, "device %s\n", dev);
|
||||||
|
|
||||||
if (mount(dev, root, container->fstype, 0, NULL) < 0) {
|
if (!strncmp(container->fstype, "xfs", strlen("xfs")))
|
||||||
|
options = "nouuid";
|
||||||
|
|
||||||
|
if (mount(dev, root, container->fstype, 0, options) < 0) {
|
||||||
perror("mount device failed");
|
perror("mount device failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
char path[512];
|
char path[512];
|
||||||
|
|
||||||
sprintf(path, "/tmp/hyper/shared/%s/", container->image);
|
sprintf(path, "%s/%s/", SHARED_DIR, container->image);
|
||||||
fprintf(stdout, "src directory %s\n", path);
|
fprintf(stdout, "src directory %s\n", path);
|
||||||
|
|
||||||
if (mount(path, root, NULL, MS_BIND, NULL) < 0) {
|
if (mount(path, root, NULL, MS_BIND, NULL) < 0) {
|
||||||
@@ -311,31 +587,63 @@ static int hyper_container_init(void *data)
|
|||||||
fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
|
fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
|
||||||
root, container->rootfs, container->exec.argv[0]);
|
root, container->rootfs, container->exec.argv[0]);
|
||||||
|
|
||||||
sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs);
|
sprintf(rootfs, "%s/%s/", root, container->rootfs);
|
||||||
if (hyper_mkdir(oldroot) < 0) {
|
if (mount(rootfs, rootfs, NULL, MS_BIND|MS_REC, NULL) < 0) {
|
||||||
perror("make oldroot directroy failed");
|
perror("failed to bind rootfs");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if (chdir(rootfs) < 0) {
|
||||||
|
perror("failed to change the root to path of the container root(before manipulating)");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount("/", oldroot, NULL, MS_BIND|MS_REC, NULL) < 0) {
|
/*
|
||||||
perror("bind oldroot failed");
|
* 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;
|
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("/");
|
if (container_setup_mount(container) < 0) {
|
||||||
|
fprintf(stderr, "container sets up mount failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore error of setup modules
|
||||||
|
container_setup_modules(container);
|
||||||
|
|
||||||
if (container_setup_volume(container) < 0) {
|
if (container_setup_volume(container) < 0) {
|
||||||
fprintf(stderr, "container sets up voulme failed\n");
|
fprintf(stderr, "container sets up voulme failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container_setup_mount(container) < 0) {
|
if (container_setup_dns(container) < 0) {
|
||||||
fprintf(stderr, "container sets up mount ns failed\n");
|
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 */
|
||||||
|
if (chroot(".") < 0) {
|
||||||
|
perror("failed to setup the root for the mount namepsace");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chdir("/") < 0) {
|
||||||
|
perror("failed chdir to the new root");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container_setup_sysctl(container) < 0) {
|
||||||
|
fprintf(stderr, "container sets up sysctl failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -344,191 +652,145 @@ static int hyper_container_init(void *data)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
container_unmount_oldroot("/.oldroot");
|
hyper_send_type(arg->pipe[1], READY);
|
||||||
|
fflush(NULL);
|
||||||
fflush(stdout);
|
_exit(0);
|
||||||
|
|
||||||
if (container_setup_tty(arg->pipe[1], container) < 0) {
|
|
||||||
fprintf(stdout, "setup tty 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);
|
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
container->exec.code = -1;
|
hyper_send_type(arg->pipe[1], ERROR);
|
||||||
hyper_send_type_block(arg->pipe[1], ERROR, 0);
|
_exit(125);
|
||||||
_exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_start_container(struct hyper_container *container)
|
static int hyper_setup_pty(struct hyper_container *c)
|
||||||
{
|
{
|
||||||
int stacksize = getpagesize() * 4;
|
char root[512];
|
||||||
void *stack = malloc(stacksize);
|
|
||||||
|
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||||
|
|
||||||
|
if (hyper_mkdir(root, 0755) < 0) {
|
||||||
|
perror("make container pts directory 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 = {
|
struct hyper_container_arg arg = {
|
||||||
.c = container,
|
.c = container,
|
||||||
|
.pod = pod,
|
||||||
|
.pipe = {-1, -1},
|
||||||
|
.pipens = {-1, -1},
|
||||||
};
|
};
|
||||||
int flags = CLONE_NEWNS | SIGCHLD;
|
int flags = CLONE_NEWNS | SIGCHLD;
|
||||||
|
char path[128];
|
||||||
|
void *stack;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
if (container->image == NULL || container->exec.argv == NULL) {
|
container->exec.pod = pod;
|
||||||
fprintf(stdout, "container root image %s, argv %p\n",
|
|
||||||
container->image, container->exec.argv);
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socketpair(PF_UNIX, SOCK_STREAM, 0, arg.pipe) < 0) {
|
if (pipe2(arg.pipe, O_CLOEXEC) < 0 || pipe2(arg.pipens, O_CLOEXEC) < 0) {
|
||||||
perror("create pipe between pod init execcmd failed");
|
perror("create pipe between pod init execcmd failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = clone(hyper_container_init, stack + stacksize, flags, &arg);
|
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");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = clone(hyper_setup_container_rootfs, stack + stacksize, flags, &arg);
|
||||||
free(stack);
|
free(stack);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
perror("create child process failed");
|
perror("create child process failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
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 */
|
/* wait for ready message */
|
||||||
if (hyper_get_type_block(arg.pipe[0], &type) < 0 || type != READY) {
|
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
|
||||||
fprintf(stdout, "wait for container started failed\n");
|
fprintf(stderr, "wait for setup container rootfs failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(arg.pipe[0]);
|
close(arg.pipe[0]);
|
||||||
close(arg.pipe[1]);
|
close(arg.pipe[1]);
|
||||||
|
close(arg.pipens[0]);
|
||||||
fprintf(stdout, "container %s init pid is %d\n", container->id, pid);
|
close(arg.pipens[1]);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
|
close(container->ns);
|
||||||
container->exec.code = -1;
|
container->ns = -1;
|
||||||
|
close(arg.pipe[0]);
|
||||||
|
close(arg.pipe[1]);
|
||||||
|
close(arg.pipens[0]);
|
||||||
|
close(arg.pipens[1]);
|
||||||
return -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;
|
struct hyper_container *c;
|
||||||
|
|
||||||
for (i = 0; i < pod->c_num; i++) {
|
list_for_each_entry(c, &pod->containers, list) {
|
||||||
c = &pod->c[i];
|
if (strlen(c->id) != strlen(id))
|
||||||
|
|
||||||
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))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strncmp(container->id, id, strlen(id)))
|
if (strncmp(c->id, id, strlen(id)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return container;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
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];
|
char root[512];
|
||||||
|
|
||||||
for (i = 0; i < pod->c_num; i++) {
|
|
||||||
c = &pod->c[i];
|
|
||||||
|
|
||||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||||
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
||||||
perror("umount devpts failed");
|
perror("umount devpts failed");
|
||||||
|
|
||||||
free(c->id);
|
close(c->ns);
|
||||||
free(c->rootfs);
|
hyper_cleanup_container_portmapping(c, pod);
|
||||||
free(c->image);
|
hyper_free_container(c);
|
||||||
free(c->workdir);
|
}
|
||||||
free(c->fstype);
|
|
||||||
|
|
||||||
for (j = 0; j < c->vols_num; j++) {
|
void hyper_cleanup_containers(struct hyper_pod *pod)
|
||||||
vol = &(c->vols[j]);
|
{
|
||||||
free(vol->device);
|
struct hyper_container *c, *n;
|
||||||
free(vol->mountpoint);
|
|
||||||
free(vol->fstype);
|
|
||||||
}
|
|
||||||
free(c->vols);
|
|
||||||
|
|
||||||
for (j = 0; j < c->envs_num; j++) {
|
list_for_each_entry_safe(c, n, &pod->containers, list)
|
||||||
env = &(c->envs[j]);
|
hyper_cleanup_container(c, pod);
|
||||||
free(env->env);
|
|
||||||
free(env->value);
|
|
||||||
}
|
|
||||||
free(c->envs);
|
|
||||||
|
|
||||||
for (j = 0; j < c->maps_num; j++) {
|
pod->remains = 0;
|
||||||
map = &(c->maps[j]);
|
|
||||||
free(map->source);
|
|
||||||
free(map->path);
|
|
||||||
}
|
|
||||||
free(c->maps);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(pod->c);
|
|
||||||
pod->c = NULL;
|
|
||||||
pod->c_num = 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+31
-14
@@ -3,45 +3,62 @@
|
|||||||
|
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
|
|
||||||
struct env {
|
|
||||||
char *env;
|
|
||||||
char *value;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct volume {
|
struct volume {
|
||||||
char *device;
|
char *device;
|
||||||
|
char *scsiaddr;
|
||||||
char *mountpoint;
|
char *mountpoint;
|
||||||
char *fstype;
|
char *fstype;
|
||||||
int readonly;
|
int readonly;
|
||||||
|
int docker;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct fsmap {
|
struct fsmap {
|
||||||
char *source;
|
char *source;
|
||||||
char *path;
|
char *path;
|
||||||
int readonly;
|
int readonly;
|
||||||
|
int docker;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sysctl {
|
||||||
|
char *path;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct port {
|
||||||
|
int host_port;
|
||||||
|
int container_port;
|
||||||
|
char *protocol;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_container {
|
struct hyper_container {
|
||||||
|
struct list_head list;
|
||||||
|
struct hyper_exec exec;
|
||||||
|
int ns;
|
||||||
|
uint32_t code;
|
||||||
|
|
||||||
|
// configs
|
||||||
char *id;
|
char *id;
|
||||||
char *rootfs;
|
char *rootfs;
|
||||||
char *image;
|
char *image;
|
||||||
char *workdir;
|
char *scsiaddr;
|
||||||
char *fstype;
|
char *fstype;
|
||||||
struct volume *vols;
|
struct volume *vols;
|
||||||
struct env *envs;
|
|
||||||
struct fsmap *maps;
|
struct fsmap *maps;
|
||||||
|
struct sysctl *sys;
|
||||||
|
struct port *ports;
|
||||||
int vols_num;
|
int vols_num;
|
||||||
int envs_num;
|
|
||||||
int maps_num;
|
int maps_num;
|
||||||
uint32_t code;
|
int sys_num;
|
||||||
struct hyper_exec exec;
|
int ports_num;
|
||||||
|
int initialize;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_pod;
|
struct hyper_pod;
|
||||||
|
|
||||||
int hyper_start_containers(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, char *id);
|
struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id);
|
||||||
int hyper_restart_containers(struct hyper_pod *pod);
|
void hyper_cleanup_container(struct hyper_container *container, struct hyper_pod *pod);
|
||||||
void hyper_cleanup_container(struct hyper_pod *pod);
|
void hyper_cleanup_containers(struct hyper_pod *pod);
|
||||||
|
void hyper_free_container(struct hyper_container *c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+60
-134
@@ -10,24 +10,25 @@
|
|||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
void hyper_reset_event(struct hyper_event *de)
|
void hyper_reset_event(struct hyper_event *he)
|
||||||
{
|
{
|
||||||
free(de->rbuf.data);
|
free(he->rbuf.data);
|
||||||
free(de->wbuf.data);
|
free(he->wbuf.data);
|
||||||
|
close(he->fd);
|
||||||
memset(de, 0, sizeof(*de));
|
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 *rbuf = &he->rbuf;
|
||||||
struct hyper_buf *wbuf = &de->wbuf;
|
struct hyper_buf *wbuf = &he->wbuf;
|
||||||
|
|
||||||
memset(rbuf, 0, sizeof(*rbuf));
|
memset(rbuf, 0, sizeof(*rbuf));
|
||||||
memset(wbuf, 0, sizeof(*wbuf));
|
memset(wbuf, 0, sizeof(*wbuf));
|
||||||
|
|
||||||
de->ops = ops;
|
he->ops = ops;
|
||||||
de->ptr = arg;
|
he->ptr = arg;
|
||||||
rbuf->size = ops->rbuf_size;
|
rbuf->size = ops->rbuf_size;
|
||||||
wbuf->size = ops->wbuf_size;
|
wbuf->size = ops->wbuf_size;
|
||||||
|
|
||||||
@@ -50,22 +51,22 @@ int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, void *
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_add_event(int efd, struct hyper_event *de, int flag)
|
int hyper_add_event(int efd, struct hyper_event *he, int flag)
|
||||||
{
|
{
|
||||||
struct epoll_event event = {
|
struct epoll_event event = {
|
||||||
.events = flag,
|
.events = flag,
|
||||||
.data.ptr = de,
|
.data.ptr = he,
|
||||||
};
|
};
|
||||||
|
|
||||||
de->flag = flag;
|
he->flag = flag;
|
||||||
if (hyper_setfd_nonblock(de->fd) < 0) {
|
if (hyper_setfd_nonblock(he->fd) < 0) {
|
||||||
perror("set fd nonblock failed");
|
perror("set fd nonblock failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "%s add event fd %d, %p\n", __func__, de->fd, de->ops);
|
fprintf(stdout, "%s add event fd %d, %p\n", __func__, he->fd, he->ops);
|
||||||
|
|
||||||
if (epoll_ctl(efd, EPOLL_CTL_ADD, de->fd, &event) < 0) {
|
if (epoll_ctl(efd, EPOLL_CTL_ADD, he->fd, &event) < 0) {
|
||||||
perror("epoll_ctl fd failed");
|
perror("epoll_ctl fd failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -73,21 +74,21 @@ int hyper_add_event(int efd, struct hyper_event *de, int flag)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_modify_event(int efd, struct hyper_event *de, int flag)
|
int hyper_modify_event(int efd, struct hyper_event *he, int flag)
|
||||||
{
|
{
|
||||||
struct epoll_event event = {
|
struct epoll_event event = {
|
||||||
.events = flag,
|
.events = flag,
|
||||||
.data.ptr = de,
|
.data.ptr = he,
|
||||||
};
|
};
|
||||||
|
|
||||||
if (de->flag == flag)
|
if (he->flag == flag)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
de->flag = flag;
|
he->flag = flag;
|
||||||
fprintf(stdout, "%s modify event fd %d, %p, event %d\n",
|
fprintf(stdout, "%s modify event fd %d, %p, event %d\n",
|
||||||
__func__, de->fd, de, flag);
|
__func__, he->fd, he, flag);
|
||||||
|
|
||||||
if (epoll_ctl(efd, EPOLL_CTL_MOD, de->fd, &event) < 0) {
|
if (epoll_ctl(efd, EPOLL_CTL_MOD, he->fd, &event) < 0) {
|
||||||
perror("epoll_ctl fd failed");
|
perror("epoll_ctl fd failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -95,106 +96,34 @@ int hyper_modify_event(int efd, struct hyper_event *de, int flag)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int hyper_getmsg_len(struct hyper_event *de, uint32_t *len)
|
int hyper_requeue_event(int efd, struct hyper_event *ev)
|
||||||
{
|
{
|
||||||
struct hyper_buf *buf = &de->rbuf;
|
struct epoll_event event = {
|
||||||
|
.events = ev->flag,
|
||||||
|
.data.ptr = ev,
|
||||||
|
};
|
||||||
|
|
||||||
if (buf->get < de->ops->len_offset + 4)
|
if (epoll_ctl(efd, EPOLL_CTL_DEL, ev->fd, NULL) < 0) {
|
||||||
return -1;
|
perror("epoll_ctl del fd failed");
|
||||||
|
|
||||||
*len = hyper_get_be32(buf->data + de->ops->len_offset);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hyper_event_read(struct hyper_event *de)
|
|
||||||
{
|
|
||||||
struct hyper_buf *buf = &de->rbuf;
|
|
||||||
uint32_t len = 4;
|
|
||||||
uint8_t data[4];
|
|
||||||
int offset = de->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);
|
|
||||||
if (size > 0) {
|
|
||||||
buf->get += size;
|
|
||||||
fprintf(stdout, "already read %" PRIu32 " bytes data\n",
|
|
||||||
buf->get);
|
|
||||||
|
|
||||||
if (de->ops->ack) {
|
|
||||||
/* control channel, need ack */
|
|
||||||
hyper_set_be32(data, size);
|
|
||||||
hyper_send_msg(de->fd, NEXT, 4, data);
|
|
||||||
}
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (errno != EAGAIN && size != 0) {
|
|
||||||
perror("fail to read");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
if (epoll_ctl(efd, EPOLL_CTL_ADD, ev->fd, &event) < 0) {
|
||||||
}
|
perror("epoll_ctl add fd failed");
|
||||||
|
|
||||||
fprintf(stdout, "get length %" PRIu32"\n", len);
|
|
||||||
if (len > buf->size) {
|
|
||||||
fprintf(stderr, "get length %" PRIu32", too long\n", len);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (buf->get < len) {
|
|
||||||
size = read(de->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) {
|
|
||||||
/* control channel, need ack */
|
|
||||||
hyper_set_be32(data, size);
|
|
||||||
hyper_send_msg(de->fd, NEXT, 4, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (errno == EINTR)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (errno != EAGAIN && size != 0) {
|
|
||||||
perror("fail to read");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* size == 0 : No one connect to qemu socket */
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* get the whole data */
|
|
||||||
if (de->ops->handle(de, len) != 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
/* len: length of the already get new data */
|
|
||||||
buf->get -= len;
|
|
||||||
memmove(buf->data, buf->data + len, buf->get);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_event_write(struct hyper_event *de)
|
int hyper_event_write(struct hyper_event *he, int efd)
|
||||||
{
|
{
|
||||||
struct hyper_buf *buf = &de->wbuf;
|
struct hyper_buf *buf = &he->wbuf;
|
||||||
uint32_t len = 0;
|
uint32_t len = 0;
|
||||||
int size = 0;
|
int size = 0;
|
||||||
|
|
||||||
while (len < buf->get) {
|
while (len < buf->get) {
|
||||||
size = write(de->fd, buf->data + len, buf->get - len);
|
size = write(he->fd, buf->data + len, buf->get - len);
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -209,46 +138,43 @@ int hyper_event_write(struct hyper_event *de)
|
|||||||
memmove(buf->data, buf->data + len, buf->get);
|
memmove(buf->data, buf->data + len, buf->get);
|
||||||
|
|
||||||
if (buf->get == 0) {
|
if (buf->get == 0) {
|
||||||
hyper_modify_event(ctl.efd, de, EPOLLIN);
|
hyper_modify_event(ctl.efd, he, he->flag & ~EPOLLOUT);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyper_event_hup(struct hyper_event *de, int efd)
|
void hyper_event_hup(struct hyper_event *he, int efd)
|
||||||
{
|
{
|
||||||
if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0)
|
if (epoll_ctl(efd, EPOLL_CTL_DEL, he->fd, NULL) < 0)
|
||||||
perror("epoll_ctl del epoll event failed");
|
perror("epoll_ctl del epoll event failed");
|
||||||
close(de->fd);
|
hyper_reset_event(he);
|
||||||
hyper_reset_event(de);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_handle_event(int efd, struct epoll_event *event)
|
int hyper_handle_event(int efd, struct epoll_event *event)
|
||||||
{
|
{
|
||||||
struct hyper_event *de = event->data.ptr;
|
struct hyper_event *he = event->data.ptr;
|
||||||
|
fprintf(stdout, "%s get event %d, he %p, fd %d. ops %p\n",
|
||||||
|
__func__, event->events, he, he->fd, he->ops);
|
||||||
|
|
||||||
if (event->events & EPOLLHUP) {
|
/* do not handle hup event if have in/out event */
|
||||||
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
|
if ((event->events & EPOLLIN) && he->ops->read) {
|
||||||
__func__, de, de->fd, de->ops);
|
fprintf(stdout, "%s event EPOLLIN, he %p, fd %d, %p\n",
|
||||||
if (de->ops->hup)
|
__func__, he, he->fd, he->ops);
|
||||||
de->ops->hup(de, efd);
|
return he->ops->read(he, efd);
|
||||||
return 0;
|
}
|
||||||
} else if (event->events & EPOLLIN) {
|
if ((event->events & EPOLLOUT) && he->ops->write) {
|
||||||
fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n",
|
fprintf(stdout, "%s event EPOLLOUT, he %p, fd %d, %p\n",
|
||||||
__func__, de, de->fd, de->ops);
|
__func__, he, he->fd, he->ops);
|
||||||
return de->ops->read(de);
|
return he->ops->write(he, efd);
|
||||||
} 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);
|
if ((event->events & EPOLLHUP) || (event->events & EPOLLERR)) {
|
||||||
return -1;
|
fprintf(stdout, "%s event EPOLLHUP or EPOLLERR, he %p, fd %d, %x\n",
|
||||||
|
__func__, he, he->fd, event->events);
|
||||||
|
if (he->ops->hup)
|
||||||
|
he->ops->hup(he, efd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
+7
-7
@@ -7,14 +7,11 @@
|
|||||||
struct hyper_event;
|
struct hyper_event;
|
||||||
|
|
||||||
struct hyper_event_ops {
|
struct hyper_event_ops {
|
||||||
int (*read)(struct hyper_event *e);
|
int (*read)(struct hyper_event *e, int efd);
|
||||||
int (*write)(struct hyper_event *e);
|
int (*write)(struct hyper_event *e, int efd);
|
||||||
int (*handle)(struct hyper_event *e, uint32_t len);
|
|
||||||
void (*hup)(struct hyper_event *e, int efd);
|
void (*hup)(struct hyper_event *e, int efd);
|
||||||
int rbuf_size;
|
int rbuf_size;
|
||||||
int wbuf_size;
|
int wbuf_size;
|
||||||
int len_offset;
|
|
||||||
int ack;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_buf {
|
struct hyper_buf {
|
||||||
@@ -32,13 +29,16 @@ struct hyper_event {
|
|||||||
void *ptr;
|
void *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define FULL(buf) \
|
||||||
|
(buf->size - buf->get <= 12)
|
||||||
|
|
||||||
int hyper_add_event(int efd, struct hyper_event *de, int flag);
|
int hyper_add_event(int efd, struct hyper_event *de, int flag);
|
||||||
int hyper_modify_event(int efd, struct hyper_event *de, int flag);
|
int hyper_modify_event(int efd, struct hyper_event *de, int flag);
|
||||||
|
int hyper_requeue_event(int efd, struct hyper_event *ev);
|
||||||
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops,
|
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops,
|
||||||
void *arg);
|
void *arg);
|
||||||
int hyper_handle_event(int efd, struct epoll_event *event);
|
int hyper_handle_event(int efd, struct epoll_event *event);
|
||||||
void hyper_reset_event(struct hyper_event *de);
|
void hyper_reset_event(struct hyper_event *de);
|
||||||
void hyper_event_hup(struct hyper_event *de, int efd);
|
void hyper_event_hup(struct hyper_event *de, int efd);
|
||||||
int hyper_event_read(struct hyper_event *de);
|
int hyper_event_write(struct hyper_event *de, int efd);
|
||||||
int hyper_event_write(struct hyper_event *de);
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+657
-384
File diff suppressed because it is too large
Load Diff
+31
-15
@@ -4,33 +4,49 @@
|
|||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
|
struct env {
|
||||||
|
char *env;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
struct hyper_exec {
|
struct hyper_exec {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct hyper_event e;
|
struct hyper_pod *pod;
|
||||||
char *id;
|
|
||||||
char *pty;
|
struct hyper_event stdinev;
|
||||||
char **argv;
|
struct hyper_event stdoutev;
|
||||||
int argc;
|
struct hyper_event stderrev;
|
||||||
uint64_t seq;
|
|
||||||
int pid;
|
int pid;
|
||||||
int ptyno;
|
int ptyno;
|
||||||
int init;
|
int init;
|
||||||
|
int ptyfd;
|
||||||
|
uint8_t close_stdin_request;
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
|
uint8_t exit;
|
||||||
|
uint8_t ref;
|
||||||
|
|
||||||
|
// configs
|
||||||
|
char *container_id;
|
||||||
|
char *user;
|
||||||
|
char *group;
|
||||||
|
char **additional_groups;
|
||||||
|
int nr_additional_groups;
|
||||||
|
struct env *envs;
|
||||||
|
int envs_num;
|
||||||
|
char **argv;
|
||||||
|
int argc;
|
||||||
|
int tty; // use tty or not
|
||||||
|
uint64_t seq;
|
||||||
|
uint64_t errseq;
|
||||||
|
char *workdir;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_pod;
|
struct hyper_pod;
|
||||||
|
|
||||||
int hyper_exec_cmd(char *json, int length);
|
int hyper_exec_cmd(char *json, int length);
|
||||||
int hyper_release_exec(struct hyper_exec *, struct hyper_pod *);
|
int hyper_run_process(struct hyper_exec *e);
|
||||||
int hyper_container_execcmd(struct hyper_pod *pod);
|
|
||||||
int hyper_setup_exec_tty(struct hyper_exec *e);
|
|
||||||
int hyper_dup_exec_tty(int fd, struct hyper_exec *e);
|
|
||||||
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
|
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
|
||||||
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
|
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
|
||||||
int hyper_send_exec_eof(int to, struct hyper_pod *pod,
|
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code);
|
||||||
struct list_head *head, int pid,
|
|
||||||
uint8_t code);
|
|
||||||
void hyper_cleanup_exec(struct hyper_pod *pod);
|
|
||||||
|
|
||||||
extern struct hyper_event_ops pts_ops;
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+58
-47
@@ -1,81 +1,92 @@
|
|||||||
#ifndef _DVM_H_
|
#ifndef _HYPER_H_
|
||||||
#define _DVM_H_
|
#define _HYPER_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "api.h"
|
||||||
#include "net.h"
|
#include "net.h"
|
||||||
#include "list.h"
|
#include "list.h"
|
||||||
#include "exec.h"
|
#include "exec.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "container.h"
|
#include "container.h"
|
||||||
|
#include "portmapping.h"
|
||||||
|
|
||||||
enum {
|
/* Path to rootfs shared directory */
|
||||||
SETDVM,
|
#define SHARED_DIR "/tmp/hyper/shared"
|
||||||
STARTPOD,
|
|
||||||
GETPOD,
|
|
||||||
STOPPOD,
|
|
||||||
DESTROYPOD,
|
|
||||||
RESTARTCONTAINER,
|
|
||||||
EXECCMD,
|
|
||||||
FINISHCMD,
|
|
||||||
READY,
|
|
||||||
ACK,
|
|
||||||
ERROR,
|
|
||||||
WINSIZE,
|
|
||||||
PING,
|
|
||||||
FINISH,
|
|
||||||
NEXT,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
POLICY_NEVER,
|
|
||||||
POLICY_ALWAYS,
|
|
||||||
POLICY_ONFAILURE,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct hyper_pod {
|
struct hyper_pod {
|
||||||
struct hyper_container *c;
|
|
||||||
struct hyper_interface *iface;
|
struct hyper_interface *iface;
|
||||||
struct hyper_route *rt;
|
struct hyper_route *rt;
|
||||||
struct list_head pe_head;
|
struct portmapping_white_list *portmap_white_lists;
|
||||||
struct list_head ce_head;
|
char **dns;
|
||||||
|
struct list_head containers;
|
||||||
|
struct list_head exec_head;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
char *tag;
|
char *share_tag;
|
||||||
char *channel;
|
|
||||||
int init_pid;
|
int init_pid;
|
||||||
uint32_t c_num;
|
|
||||||
uint32_t i_num;
|
uint32_t i_num;
|
||||||
uint32_t r_num;
|
uint32_t r_num;
|
||||||
uint32_t e_num;
|
uint32_t d_num;
|
||||||
uint32_t type;
|
/* how many containers are running */
|
||||||
uint32_t code;
|
|
||||||
uint32_t remains;
|
uint32_t remains;
|
||||||
uint8_t policy;
|
int req_destroy;
|
||||||
int efd;
|
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 {
|
struct hyper_win_size {
|
||||||
char *tty;
|
|
||||||
int row;
|
int row;
|
||||||
int column;
|
int column;
|
||||||
uint64_t seq;
|
uint64_t seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_ctl {
|
struct file_command {
|
||||||
int efd;
|
char *id;
|
||||||
struct hyper_event sig;
|
char *file;
|
||||||
struct hyper_event tty;
|
|
||||||
struct hyper_event chan;
|
|
||||||
struct hyper_event ctl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int hyper_mkdir(char *hyper_path);
|
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);
|
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);
|
||||||
|
void hyper_pod_destroyed(int failed);
|
||||||
|
|
||||||
extern struct hyper_pod global_pod;
|
extern struct hyper_pod global_pod;
|
||||||
extern struct hyper_ctl ctl;
|
extern struct hyper_ctl ctl;
|
||||||
extern struct hyper_exec *global_exec;
|
extern sigset_t orig_mask;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+772
-483
File diff suppressed because it is too large
Load Diff
+10
-3
@@ -164,14 +164,18 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
|||||||
int i;
|
int i;
|
||||||
jsmntok_t *token;
|
jsmntok_t *token;
|
||||||
int count = 0;
|
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;
|
char c;
|
||||||
jsmntype_t type;
|
jsmntype_t type;
|
||||||
|
|
||||||
c = js[parser->pos];
|
c = js[parser->pos];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '{': case '[':
|
case '{':
|
||||||
|
num++;
|
||||||
|
case '[':
|
||||||
count++;
|
count++;
|
||||||
if (tokens == NULL)
|
if (tokens == NULL)
|
||||||
break;
|
break;
|
||||||
@@ -189,7 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
|||||||
token->start = parser->pos;
|
token->start = parser->pos;
|
||||||
parser->toksuper = parser->toknext - 1;
|
parser->toksuper = parser->toknext - 1;
|
||||||
break;
|
break;
|
||||||
case '}': case ']':
|
case '}':
|
||||||
|
if (--num <= 0)
|
||||||
|
out = 1;
|
||||||
|
case ']':
|
||||||
if (tokens == NULL)
|
if (tokens == NULL)
|
||||||
break;
|
break;
|
||||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||||
|
|||||||
@@ -10,6 +10,8 @@
|
|||||||
#include <termios.h>
|
#include <termios.h>
|
||||||
|
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "parse.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
void hyper_set_be32(uint8_t *buf, uint32_t val)
|
void hyper_set_be32(uint8_t *buf, uint32_t val)
|
||||||
@@ -46,7 +48,6 @@ int hyper_send_data(int fd, uint8_t *data, uint32_t len)
|
|||||||
|
|
||||||
while (length < len) {
|
while (length < len) {
|
||||||
size = write(fd, data + length, len - length);
|
size = write(fd, data + length, len - length);
|
||||||
|
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -90,14 +91,13 @@ int hyper_send_type(int fd, uint32_t type)
|
|||||||
return hyper_send_msg(fd, type, 0, NULL);
|
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;
|
int len = 0, size;
|
||||||
uint8_t buf[8];
|
uint8_t buf[8];
|
||||||
|
|
||||||
while (len < 8) {
|
while (len < 8) {
|
||||||
size = read(fd, buf + len, 8 - len);
|
size = read(fd, buf + len, 8 - len);
|
||||||
|
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
@@ -111,42 +111,20 @@ int hyper_get_type_block(int fd, uint32_t *type)
|
|||||||
return 0;
|
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;
|
int ret, flags;
|
||||||
uint32_t t;
|
|
||||||
|
|
||||||
flags = fcntl(fd, F_GETFL, 0);
|
flags = hyper_setfd_block(fd);
|
||||||
if (flags < 0) {
|
if (flags < 0) {
|
||||||
fprintf(stderr, "get fd flag failed\n");
|
fprintf(stderr, "%s fail to set fd block\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) {
|
ret = hyper_send_msg(fd, type, len, data);
|
||||||
perror("set fd BLOCK failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = hyper_send_msg(fd, type, 0, NULL);
|
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||||
if (ret < 0)
|
perror("restore fd flag failed");
|
||||||
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");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -199,7 +177,7 @@ static int addattr_l(struct nlmsghdr *n, int maxlen, int type, void *data, int a
|
|||||||
static int hyper_get_ifindex(char *nic)
|
static int hyper_get_ifindex(char *nic)
|
||||||
{
|
{
|
||||||
int fd, ifindex = -1;
|
int fd, ifindex = -1;
|
||||||
char path[512], buf[4];
|
char path[512], buf[8];
|
||||||
|
|
||||||
fprintf(stdout, "net device %s\n", nic);
|
fprintf(stdout, "net device %s\n", nic);
|
||||||
sprintf(path, "/sys/class/net/%s/ifindex", nic);
|
sprintf(path, "/sys/class/net/%s/ifindex", nic);
|
||||||
@@ -212,7 +190,7 @@ static int hyper_get_ifindex(char *nic)
|
|||||||
}
|
}
|
||||||
|
|
||||||
memset(buf, 0, sizeof(buf));
|
memset(buf, 0, sizeof(buf));
|
||||||
if (read(fd, buf, sizeof(buf)) <= 0) {
|
if (read(fd, buf, sizeof(buf) - 1) <= 0) {
|
||||||
perror("can read open file");
|
perror("can read open file");
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -307,14 +285,17 @@ static int hyper_remove_nic(char *device)
|
|||||||
{
|
{
|
||||||
char path[256], real[128];
|
char path[256], real[128];
|
||||||
int fd;
|
int fd;
|
||||||
|
ssize_t size;
|
||||||
|
|
||||||
sprintf(path, "/sys/class/net/%s", device);
|
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");
|
perror("fail to read link directory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
real[size] = '\0';
|
||||||
sprintf(path, "/sys/%s/../../../remove", real + 5);
|
sprintf(path, "/sys/%s/../../../remove", real + 5);
|
||||||
|
|
||||||
fprintf(stdout, "get net sys path %s\n", path);
|
fprintf(stdout, "get net sys path %s\n", path);
|
||||||
@@ -447,8 +428,13 @@ static int hyper_setup_route(struct rtnl_handle *rth,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rt->device) {
|
if (rt->device) {
|
||||||
rt->ifindex = hyper_get_ifindex(rt->device);
|
int ifindex = hyper_get_ifindex(rt->device);
|
||||||
if (addattr_l(&req.n, sizeof(req), RTA_OIF, &rt->ifindex, 4)) {
|
if (ifindex < 0) {
|
||||||
|
fprintf(stderr, "failed to get the ifindix of %s\n", rt->device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addattr_l(&req.n, sizeof(req), RTA_OIF, &ifindex, 4)) {
|
||||||
fprintf(stderr, "setup oif attr failed\n");
|
fprintf(stderr, "setup oif attr failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -530,7 +516,13 @@ static int hyper_cleanup_route(struct rtnl_handle *rth, struct hyper_route *rt)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (rt->device) {
|
if (rt->device) {
|
||||||
if (addattr_l(&req.n, sizeof(req), RTA_OIF, &rt->ifindex, 4)) {
|
int ifindex = hyper_get_ifindex(rt->device);
|
||||||
|
if (ifindex < 0) {
|
||||||
|
fprintf(stderr, "failed to get the ifindix of %s\n", rt->device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addattr_l(&req.n, sizeof(req), RTA_OIF, &ifindex, 4)) {
|
||||||
fprintf(stderr, "setup oif attr failed\n");
|
fprintf(stderr, "setup oif attr failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -573,6 +565,44 @@ static int hyper_cleanup_route(struct rtnl_handle *rth, struct hyper_route *rt)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int hyper_set_interface_name(struct rtnl_handle *rth,
|
||||||
|
int ifindex,
|
||||||
|
char *new_device_name)
|
||||||
|
{
|
||||||
|
struct {
|
||||||
|
struct nlmsghdr n;
|
||||||
|
struct ifinfomsg i;
|
||||||
|
char buf[1024];
|
||||||
|
} req;
|
||||||
|
|
||||||
|
if (ifindex < 0 || !new_device_name) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(&req, 0, sizeof(req));
|
||||||
|
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
|
||||||
|
req.n.nlmsg_flags = NLM_F_REQUEST;
|
||||||
|
req.n.nlmsg_type = RTM_SETLINK;
|
||||||
|
|
||||||
|
req.i.ifi_family = AF_UNSPEC;
|
||||||
|
req.i.ifi_change = 0xFFFFFFFF;
|
||||||
|
req.i.ifi_index = ifindex;
|
||||||
|
|
||||||
|
if (addattr_l(&req.n, sizeof(req), IFLA_IFNAME,
|
||||||
|
new_device_name,
|
||||||
|
strlen(new_device_name) + 1)) {
|
||||||
|
fprintf(stderr, "setup attr failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rtnl_talk(rth, &req.n, 0, 0, NULL) < 0) {
|
||||||
|
perror("rtnl_talk failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int hyper_setup_interface(struct rtnl_handle *rth,
|
static int hyper_setup_interface(struct rtnl_handle *rth,
|
||||||
struct hyper_interface *iface)
|
struct hyper_interface *iface)
|
||||||
{
|
{
|
||||||
@@ -583,6 +613,7 @@ static int hyper_setup_interface(struct rtnl_handle *rth,
|
|||||||
struct ifaddrmsg ifa;
|
struct ifaddrmsg ifa;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
} req;
|
} req;
|
||||||
|
int ifindex;
|
||||||
|
|
||||||
if (!(iface->device && iface->ipaddr && iface->mask)) {
|
if (!(iface->device && iface->ipaddr && iface->mask)) {
|
||||||
fprintf(stderr, "interface information incorrect\n");
|
fprintf(stderr, "interface information incorrect\n");
|
||||||
@@ -595,8 +626,13 @@ static int hyper_setup_interface(struct rtnl_handle *rth,
|
|||||||
req.n.nlmsg_type = RTM_NEWADDR;
|
req.n.nlmsg_type = RTM_NEWADDR;
|
||||||
req.ifa.ifa_family = AF_INET;
|
req.ifa.ifa_family = AF_INET;
|
||||||
|
|
||||||
iface->ifindex = hyper_get_ifindex(iface->device);
|
ifindex = hyper_get_ifindex(iface->device);
|
||||||
req.ifa.ifa_index = iface->ifindex;
|
if (ifindex < 0) {
|
||||||
|
fprintf(stderr, "failed to get the ifindix of %s\n", iface->device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.ifa.ifa_index = ifindex;
|
||||||
req.ifa.ifa_scope = 0;
|
req.ifa.ifa_scope = 0;
|
||||||
|
|
||||||
if (get_addr_ipv4((uint8_t *)&data, iface->ipaddr) <= 0) {
|
if (get_addr_ipv4((uint8_t *)&data, iface->ipaddr) <= 0) {
|
||||||
@@ -621,8 +657,13 @@ static int hyper_setup_interface(struct rtnl_handle *rth,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hyper_up_nic(rth, iface->ifindex) < 0) {
|
if (iface->new_device_name && strcmp(iface->new_device_name, iface->device)) {
|
||||||
fprintf(stderr, "up device %d failed\n", iface->ifindex);
|
fprintf(stdout, "Setting interface name to %s\n", iface->new_device_name);
|
||||||
|
hyper_set_interface_name(rth, ifindex, iface->new_device_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_up_nic(rth, ifindex) < 0) {
|
||||||
|
fprintf(stderr, "up device %d failed\n", ifindex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,6 +680,7 @@ static int hyper_cleanup_interface(struct rtnl_handle *rth,
|
|||||||
struct ifaddrmsg ifa;
|
struct ifaddrmsg ifa;
|
||||||
char buf[256];
|
char buf[256];
|
||||||
} req;
|
} req;
|
||||||
|
int ifindex;
|
||||||
|
|
||||||
if (!(iface->device && iface->ipaddr && iface->mask)) {
|
if (!(iface->device && iface->ipaddr && iface->mask)) {
|
||||||
fprintf(stderr, "interface information incorrect\n");
|
fprintf(stderr, "interface information incorrect\n");
|
||||||
@@ -651,7 +693,13 @@ static int hyper_cleanup_interface(struct rtnl_handle *rth,
|
|||||||
req.n.nlmsg_type = RTM_DELADDR;
|
req.n.nlmsg_type = RTM_DELADDR;
|
||||||
req.ifa.ifa_family = AF_INET;
|
req.ifa.ifa_family = AF_INET;
|
||||||
|
|
||||||
req.ifa.ifa_index = iface->ifindex;
|
ifindex = hyper_get_ifindex(iface->device);
|
||||||
|
if (ifindex < 0) {
|
||||||
|
fprintf(stderr, "failed to get the ifindix of %s\n", iface->device);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
req.ifa.ifa_index = ifindex;
|
||||||
req.ifa.ifa_scope = 0;
|
req.ifa.ifa_scope = 0;
|
||||||
|
|
||||||
if (get_addr_ipv4((uint8_t *)&data, iface->ipaddr) <= 0) {
|
if (get_addr_ipv4((uint8_t *)&data, iface->ipaddr) <= 0) {
|
||||||
@@ -676,8 +724,13 @@ static int hyper_cleanup_interface(struct rtnl_handle *rth,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hyper_down_nic(rth, iface->ifindex) < 0) {
|
/* Don't down&remove lo device */
|
||||||
fprintf(stderr, "up device %d failed\n", iface->ifindex);
|
if (strcmp(iface->device, "lo") == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_down_nic(rth, ifindex) < 0) {
|
||||||
|
fprintf(stderr, "up device %d failed\n", ifindex);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,3 +848,130 @@ void hyper_cleanup_network(struct hyper_pod *pod)
|
|||||||
pod->i_num = 0;
|
pod->i_num = 0;
|
||||||
netlink_close(&rth);
|
netlink_close(&rth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hyper_cmd_setup_interface(char *json, int length)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
struct hyper_interface *iface;
|
||||||
|
struct rtnl_handle rth;
|
||||||
|
|
||||||
|
if (hyper_rescan() < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (netlink_open(&rth) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
|
||||||
|
iface = hyper_parse_setup_interface(json, length);
|
||||||
|
if (iface == NULL) {
|
||||||
|
fprintf(stderr, "parse interface failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
ret = hyper_setup_interface(&rth, iface);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "link up device %s failed\n", iface->device);
|
||||||
|
goto out1;
|
||||||
|
}
|
||||||
|
ret = 0;
|
||||||
|
out1:
|
||||||
|
free(iface->device);
|
||||||
|
free(iface->ipaddr);
|
||||||
|
free(iface->mask);
|
||||||
|
free(iface);
|
||||||
|
out:
|
||||||
|
netlink_close(&rth);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hyper_cmd_setup_route(char *json, int length) {
|
||||||
|
struct hyper_route *rts = NULL;
|
||||||
|
int i, ret = -1;
|
||||||
|
uint32_t r_num;
|
||||||
|
struct rtnl_handle rth;
|
||||||
|
|
||||||
|
if (netlink_open(&rth) < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hyper_parse_setup_routes(&rts, &r_num, json, length) < 0) {
|
||||||
|
fprintf(stderr, "parse route failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < r_num; i++) {
|
||||||
|
ret = hyper_setup_route(&rth, &rts[i]);
|
||||||
|
if (ret < 0) {
|
||||||
|
fprintf(stderr, "setup route failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
|
netlink_close(&rth);
|
||||||
|
free(rts);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hyper_setup_dns(struct hyper_pod *pod)
|
||||||
|
{
|
||||||
|
int 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;
|
||||||
|
|
||||||
|
if (pod->dns == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -18,26 +18,17 @@ struct rtnl_handle {
|
|||||||
__u32 dump;
|
__u32 dump;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
__u8 family;
|
|
||||||
__u8 bytelen;
|
|
||||||
__s16 bitlen;
|
|
||||||
__u32 flags;
|
|
||||||
__u32 data[8];
|
|
||||||
} inet_prefix;
|
|
||||||
|
|
||||||
struct hyper_interface {
|
struct hyper_interface {
|
||||||
char *device;
|
char *device;
|
||||||
int ifindex;
|
|
||||||
char *ipaddr;
|
char *ipaddr;
|
||||||
char *mask;
|
char *mask;
|
||||||
|
char *new_device_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_route {
|
struct hyper_route {
|
||||||
char *dst;
|
char *dst;
|
||||||
char *gw;
|
char *gw;
|
||||||
char *device;
|
char *device;
|
||||||
int ifindex;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_pod;
|
struct hyper_pod;
|
||||||
@@ -47,11 +38,15 @@ uint32_t hyper_get_be32(uint8_t *buf);
|
|||||||
void hyper_set_be64(uint8_t *buf, uint64_t val);
|
void hyper_set_be64(uint8_t *buf, uint64_t val);
|
||||||
uint64_t hyper_get_be64(uint8_t *buf);
|
uint64_t hyper_get_be64(uint8_t *buf);
|
||||||
int hyper_setup_network(struct hyper_pod *pod);
|
int hyper_setup_network(struct hyper_pod *pod);
|
||||||
|
int hyper_cmd_setup_interface(char *json, int length);
|
||||||
|
int hyper_cmd_setup_route(char *json, int length);
|
||||||
void hyper_cleanup_network(struct hyper_pod *pod);
|
void hyper_cleanup_network(struct hyper_pod *pod);
|
||||||
int hyper_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(int fd, uint32_t type);
|
||||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack);
|
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,
|
int hyper_send_msg(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||||
uint8_t *message);
|
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);
|
int hyper_send_data(int fd, uint8_t *data, uint32_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+1017
-223
File diff suppressed because it is too large
Load Diff
+9
-2
@@ -1,13 +1,20 @@
|
|||||||
#ifndef _DVM_JSON_H_
|
#ifndef _PARSE_H_
|
||||||
#define _DVM_JSON_H_
|
#define _PARSE_H_
|
||||||
|
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
#include "jsmn.h"
|
#include "jsmn.h"
|
||||||
|
#include "parson.h"
|
||||||
|
|
||||||
int hyper_parse_pod(struct hyper_pod *pod, char *json, int length);
|
int hyper_parse_pod(struct hyper_pod *pod, char *json, int length);
|
||||||
struct hyper_exec *hyper_parse_execcmd(char *json, int length);
|
struct hyper_exec *hyper_parse_execcmd(char *json, int length);
|
||||||
char *json_token_str(char *js, jsmntok_t *t);
|
char *json_token_str(char *js, jsmntok_t *t);
|
||||||
int json_token_streq(char *js, jsmntok_t *t, char *s);
|
int json_token_streq(char *js, jsmntok_t *t, char *s);
|
||||||
int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length);
|
int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length);
|
||||||
|
int hyper_parse_file_command(struct file_command *cmd, 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
|
#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,417 @@
|
|||||||
|
#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("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, "iptables -t %s -C %s %s", rule.table, rule.chain, rule.rule);
|
||||||
|
sprintf(cmd, "iptables -t %s %s %s %s", rule.table, rule.op, rule.chain, rule.rule);
|
||||||
|
} else {
|
||||||
|
sprintf(cmd, "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)
|
||||||
|
{
|
||||||
|
const char *connmax = "10485760";
|
||||||
|
const char *timeout = "300";
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* portmapping enables nf_conntrack by default, should blow up nf_conntack_max to make sure
|
||||||
|
* nf_conntrack is available for connections. */
|
||||||
|
if (hyper_write_file("/proc/sys/net/nf_conntrack_max", connmax, strlen(connmax)) < 0) {
|
||||||
|
fprintf(stderr, "sysctl: setup default nf_conntrack_max(%s) failed\n", connmax);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_write_file("/proc/sys/net/netfilter/nf_conntrack_tcp_timeout_established", timeout, strlen(timeout)) < 0) {
|
||||||
|
fprintf(stderr, "sysctl: setup default nf_conntrack_tcp_timeout_established(%s) failed\n", timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only allow network request from internal white list
|
||||||
|
int i = 0, j = 0;
|
||||||
|
char rule[128] = {0};
|
||||||
|
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
|
||||||
|
sprintf(rule, "-s %s -j ACCEPT",
|
||||||
|
pod->portmap_white_lists->internal_networks[j]);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->ports_num == 0) {
|
||||||
|
return 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int i = 0, j = 0;
|
||||||
|
char rule[128] = {0};
|
||||||
|
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
|
||||||
|
sprintf(rule, "-s %s -j ACCEPT",
|
||||||
|
pod->portmap_white_lists->internal_networks[j]);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (c->ports_num == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -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
|
||||||
+393
-87
@@ -9,13 +9,19 @@
|
|||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/reboot.h>
|
#include <sys/reboot.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
|
#include "container.h"
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
char *read_cmdline(void)
|
char *read_cmdline(void)
|
||||||
@@ -23,6 +29,22 @@ char *read_cmdline(void)
|
|||||||
return NULL;
|
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)
|
int hyper_list_dir(char *path)
|
||||||
{
|
{
|
||||||
struct dirent **list;
|
struct dirent **list;
|
||||||
@@ -39,52 +61,351 @@ int hyper_list_dir(char *path)
|
|||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
dir = list[i];
|
dir = list[i];
|
||||||
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
||||||
|
free(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(list);
|
free(list);
|
||||||
return 0;
|
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("hwclock", "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;
|
struct stat st;
|
||||||
char *p, *path = strdup(hyper_path);
|
char *p, *path = strdup(hyper_path);
|
||||||
|
|
||||||
if (path == NULL) {
|
if (path == NULL) {
|
||||||
errno = ENOMEM;
|
errno = ENOMEM;
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "create directory %s\n", path);
|
|
||||||
if (stat(path, &st) >= 0) {
|
if (stat(path, &st) >= 0) {
|
||||||
if (S_ISDIR(st.st_mode))
|
if (S_ISDIR(st.st_mode))
|
||||||
return 0;
|
goto out;
|
||||||
errno = ENOTDIR;
|
errno = ENOTDIR;
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (errno != ENOENT)
|
if (errno != ENOENT)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
p = strrchr(path, '/');
|
p = strrchr(path, '/');
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
errno = EINVAL;
|
errno = EINVAL;
|
||||||
return -1;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p != path) {
|
if (p != path) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
|
|
||||||
if (hyper_mkdir(path) < 0)
|
if (hyper_mkdir(path, mode) < 0)
|
||||||
return -1;
|
goto fail;
|
||||||
|
|
||||||
*p = '/';
|
*p = '/';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mkdir(path, 0755) < 0 && errno != EEXIST)
|
fprintf(stdout, "create directory %s\n", path);
|
||||||
return -1;
|
if (mkdir(path, mode) < 0 && errno != EEXIST) {
|
||||||
|
perror("failed to create directory");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
out:
|
||||||
|
free(path);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(path);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void online_cpu(void)
|
||||||
|
{
|
||||||
|
DIR *dir = opendir("/sys/devices/system/cpu");
|
||||||
|
if (dir == NULL) {
|
||||||
|
fprintf(stderr, "open dir /sys/devices/system/cpu failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("online_cpu()\n");
|
||||||
|
for (;;) {
|
||||||
|
int num;
|
||||||
|
int ret;
|
||||||
|
char path[256];
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
struct dirent *entry = readdir(dir);
|
||||||
|
if (entry == NULL)
|
||||||
|
break;
|
||||||
|
if (entry->d_type != DT_DIR)
|
||||||
|
continue;
|
||||||
|
ret = sscanf(entry->d_name, "cpu%d", &num);
|
||||||
|
if (ret < 1 || num == 0) /* skip none cpu%d and cpu0 */
|
||||||
|
continue;
|
||||||
|
sprintf(path, "/sys/devices/system/cpu/%s/online", entry->d_name);
|
||||||
|
fd = open(path, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "open %s failed\n", path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("try to online %s\n", entry->d_name);
|
||||||
|
ret = write(fd, "1", sizeof("1"));
|
||||||
|
printf("online %s result: %s\n", entry->d_name, ret == 2 ? "success" : "failed");
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
void online_memory(void)
|
||||||
|
{
|
||||||
|
DIR *dir = opendir("/sys/devices/system/memory");
|
||||||
|
if (dir == NULL) {
|
||||||
|
fprintf(stderr, "open dir /sys/devices/system/memory failed\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("online_memory()\n");
|
||||||
|
for (;;) {
|
||||||
|
int num;
|
||||||
|
int ret;
|
||||||
|
char path[256];
|
||||||
|
int fd;
|
||||||
|
|
||||||
|
struct dirent *entry = readdir(dir);
|
||||||
|
if (entry == NULL)
|
||||||
|
break;
|
||||||
|
if (entry->d_type != DT_DIR)
|
||||||
|
continue;
|
||||||
|
ret = sscanf(entry->d_name, "memory%d", &num);
|
||||||
|
if (ret < 1 || num == 0) /* skip none memory%d and memory0 */
|
||||||
|
continue;
|
||||||
|
sprintf(path, "/sys/devices/system/memory/%s/online", entry->d_name);
|
||||||
|
fd = open(path, O_RDWR);
|
||||||
|
if (fd < 0) {
|
||||||
|
fprintf(stderr, "open %s failed\n", path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf("try to online %s\n", entry->d_name);
|
||||||
|
ret = write(fd, "1", sizeof("1"));
|
||||||
|
printf("online %s result: %s\n", entry->d_name, ret == 2 ? "success" : "failed");
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
closedir(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if WITH_VBOX
|
#if WITH_VBOX
|
||||||
@@ -94,13 +415,12 @@ int hyper_open_channel(char *channel, int mode)
|
|||||||
{
|
{
|
||||||
struct termios term;
|
struct termios term;
|
||||||
int fd = open(channel, O_RDWR | O_CLOEXEC | mode);
|
int fd = open(channel, O_RDWR | O_CLOEXEC | mode);
|
||||||
fprintf(stdout, "open %s get %d\n", channel, fd);
|
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("fail to open channel device");
|
perror("fail to open channel device");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "open %s get %d\n", channel, fd);
|
||||||
bzero(&term, sizeof(term));
|
bzero(&term, sizeof(term));
|
||||||
|
|
||||||
cfmakeraw(&term);
|
cfmakeraw(&term);
|
||||||
@@ -174,7 +494,6 @@ int hyper_insmod(char *module)
|
|||||||
ret = 0;
|
ret = 0;
|
||||||
out:
|
out:
|
||||||
close(fd);
|
close(fd);
|
||||||
if (buf)
|
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -192,7 +511,7 @@ int hyper_open_channel(char *channel, int mode)
|
|||||||
|
|
||||||
num = scandir("/sys/class/virtio-ports/", &list, NULL, NULL);
|
num = scandir("/sys/class/virtio-ports/", &list, NULL, NULL);
|
||||||
if (num < 0) {
|
if (num < 0) {
|
||||||
perror("scan /sys/calss/virtio-ports/ failed");
|
perror("scan /sys/class/virtio-ports/ failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +537,6 @@ int hyper_open_channel(char *channel, int mode)
|
|||||||
fd = -1;
|
fd = -1;
|
||||||
|
|
||||||
if (strncmp(name, channel, strlen(channel))) {
|
if (strncmp(name, channel, strlen(channel))) {
|
||||||
fprintf(stderr, "channel %s, directory %s\n", channel, name);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -245,16 +563,6 @@ int hyper_insmod(char *module)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int hyper_open_serial_dev(char *tty)
|
|
||||||
{
|
|
||||||
int fd = open(tty, O_RDWR | O_CLOEXEC | O_NOCTTY);
|
|
||||||
|
|
||||||
if (fd < 0)
|
|
||||||
perror("fail to open tty device");
|
|
||||||
|
|
||||||
return fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int hyper_setfd_cloexec(int fd)
|
int hyper_setfd_cloexec(int fd)
|
||||||
{
|
{
|
||||||
int flags = fcntl(fd, F_GETFD);
|
int flags = fcntl(fd, F_GETFD);
|
||||||
@@ -286,7 +594,7 @@ int hyper_setfd_block(int fd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_setfd_nonblock(int fd)
|
int hyper_setfd_nonblock(int fd)
|
||||||
@@ -303,10 +611,10 @@ int hyper_setfd_nonblock(int fd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyper_unmount_all(void)
|
static void hyper_unmount_all(void)
|
||||||
{
|
{
|
||||||
FILE *mtab;
|
FILE *mtab;
|
||||||
struct mntent *mnt;
|
struct mntent *mnt;
|
||||||
@@ -346,69 +654,67 @@ void hyper_unmount_all(void)
|
|||||||
fprintf(stdout, ("umount %s: %s failed\n"),
|
fprintf(stdout, ("umount %s: %s failed\n"),
|
||||||
filesys, strerror(errno));
|
filesys, strerror(errno));
|
||||||
}
|
}
|
||||||
|
free(filesys);
|
||||||
|
mntlist[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyper_kill_all(void)
|
void hyper_shutdown()
|
||||||
{
|
{
|
||||||
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_unmount_all();
|
hyper_unmount_all();
|
||||||
|
|
||||||
reboot(LINUX_REBOOT_CMD_POWER_OFF);
|
reboot(LINUX_REBOOT_CMD_POWER_OFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hyper_cmd(char *cmd)
|
||||||
|
{
|
||||||
|
int pid, status;
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
perror("fail to fork");
|
||||||
|
return -1;
|
||||||
|
} else if (pid > 0) {
|
||||||
|
if (waitpid(pid, &status, 0) <= 0) {
|
||||||
|
perror("waiting fork cmd failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (WIFEXITED(status)) {
|
||||||
|
int ret = WEXITSTATUS(status);
|
||||||
|
fprintf(stdout, "%s cmd exit normally, status %" PRIu8 "\n", cmd, ret);
|
||||||
|
if (ret == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "cmd %s exit unexpectedly, status %" PRIu8 "\n", cmd, status);
|
||||||
|
return -1;
|
||||||
|
} else {
|
||||||
|
fprintf(stdout, "executing cmd %s\n", cmd);
|
||||||
|
execlp("sh", "sh", "-c", cmd, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ssize_t nonblock_read(int fd, void *buf, size_t count)
|
||||||
|
{
|
||||||
|
ssize_t len = 0, ret = 0;
|
||||||
|
|
||||||
|
while (len < count) {
|
||||||
|
ret = read(fd, buf + len, count - len);
|
||||||
|
if (ret <= 0) {
|
||||||
|
if (errno == EINTR) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (errno == EAGAIN) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return len > 0 ? len : ret;
|
||||||
|
}
|
||||||
|
|||||||
+21
-7
@@ -2,28 +2,42 @@
|
|||||||
#define _UTIL_H_
|
#define _UTIL_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <grp.h>
|
||||||
|
#include <pwd.h>
|
||||||
#include "../config.h"
|
#include "../config.h"
|
||||||
|
|
||||||
struct hyper_pod;
|
struct hyper_pod;
|
||||||
|
struct env;
|
||||||
|
|
||||||
#ifdef WITH_DEBUG
|
#ifdef WITH_DEBUG
|
||||||
#define dprintf(fmt, ...) \
|
#define dprintf(fmt, ...) \
|
||||||
fprintf(stdout, fmt, ##_VA_ARGS__)
|
fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||||
#else
|
#else
|
||||||
#define dprintf(fmr, ...)
|
#define dprintf(fmr, ...)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
char *read_cmdline(void);
|
char *read_cmdline(void);
|
||||||
|
int hyper_setup_env(struct env *envs, int num);
|
||||||
|
int hyper_find_sd(char *addr, char **dev);
|
||||||
int hyper_list_dir(char *path);
|
int hyper_list_dir(char *path);
|
||||||
int hyper_mkdir(char *path);
|
int hyper_copy_dir(char *src, char *dst);
|
||||||
|
void hyper_sync_time_hctosys();
|
||||||
|
void online_cpu(void);
|
||||||
|
void online_memory(void);
|
||||||
|
int hyper_cmd(char *cmd);
|
||||||
|
int hyper_create_file(const char *hyper_path);
|
||||||
|
void hyper_filize(char *hyper_path);
|
||||||
|
int hyper_mkdir(char *path, mode_t mode);
|
||||||
|
int hyper_write_file(const char *path, const char *value, size_t len);
|
||||||
int hyper_open_channel(char *channel, int mode);
|
int hyper_open_channel(char *channel, int mode);
|
||||||
int hyper_open_serial_dev(char *tty);
|
|
||||||
int hyper_setfd_cloexec(int fd);
|
int hyper_setfd_cloexec(int fd);
|
||||||
int hyper_setfd_block(int fd);
|
int hyper_setfd_block(int fd);
|
||||||
int hyper_setfd_nonblock(int fd);
|
int hyper_setfd_nonblock(int fd);
|
||||||
void hyper_shutdown(struct hyper_pod *pod);
|
int hyper_socketpair(int domain, int type, int protocol, int sv[2]);
|
||||||
int hyper_send_finish(struct hyper_pod *pod);
|
void hyper_shutdown();
|
||||||
void hyper_kill_all(void);
|
|
||||||
void hyper_unmount_all(void);
|
|
||||||
int hyper_insmod(char *module);
|
int hyper_insmod(char *module);
|
||||||
|
struct passwd *hyper_getpwnam(const char *name);
|
||||||
|
struct group *hyper_getgrnam(const char *name);
|
||||||
|
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
|
||||||
|
ssize_t nonblock_read(int fd, void *buf, size_t count);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user