mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-09-06 05:31:58 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f359cb9468 | ||
|
|
3de74e927c | ||
|
|
7b54d5c9da | ||
|
|
1e4711d898 | ||
|
|
cb71f43ed1 | ||
|
|
c72276b004 | ||
|
|
5735f9f674 | ||
|
|
de0c2c97e4 | ||
|
|
8a86dd1f51 | ||
|
|
5ba9b2550d | ||
|
|
da986b4a3a | ||
|
|
2f4626dde2 | ||
|
|
bf61d6306e | ||
|
|
74f6930073 | ||
|
|
0c05c999e3 | ||
|
|
97099eb46e | ||
|
|
b28a02fa0d | ||
|
|
9a6738d84d | ||
|
|
d3cfa23dde | ||
|
|
9bfb3be414 | ||
|
|
ae2d491c20 | ||
|
|
b0a601793e | ||
|
|
19f1dc012e | ||
|
|
87b1a5c29a | ||
|
|
4a63bceb67 | ||
|
|
b2f6b89ea6 | ||
|
|
db4f364510 | ||
|
|
2ccea842bd | ||
|
|
3197bcad45 | ||
|
|
3bed96c176 | ||
|
|
eecb4c5612 | ||
|
|
c015887bb6 | ||
|
|
2169309145 | ||
|
|
c5d25b6f5f | ||
|
|
da6b36411a | ||
|
|
06d10f2844 | ||
|
|
70d35640b9 | ||
|
|
1f501c5417 | ||
|
|
1c21bb2e6f | ||
|
|
b6c6e1f991 | ||
|
|
98059369b8 | ||
|
|
03187117e1 | ||
|
|
54aed5efc5 | ||
|
|
98b8211ddc | ||
|
|
cd9a8f4306 | ||
|
|
bb550c2444 | ||
|
|
00308d00b5 | ||
|
|
e255de660d | ||
|
|
ca004ec273 | ||
|
|
52aca5a860 | ||
|
|
5fcac6f0bb | ||
|
|
216bce6fe0 | ||
|
|
e8381942d4 | ||
|
|
51dc391bc0 | ||
|
|
73a9c3e8e9 | ||
|
|
505ad4ddb0 | ||
|
|
20158b9033 | ||
|
|
1e6dffd36f | ||
|
|
d919414192 | ||
|
|
b15d771a56 | ||
|
|
b99768db28 | ||
|
|
1a612982e8 | ||
|
|
3f034fec04 | ||
|
|
831113b7d0 | ||
|
|
64aeb1ceca | ||
|
|
11c7507eed | ||
|
|
828204c1cf | ||
|
|
94720f4ace | ||
|
|
12a797cb9e | ||
|
|
7856628d8a | ||
|
|
193c1cc97e | ||
|
|
c3eee6616f | ||
|
|
3d57690daa | ||
|
|
9ca23869fc | ||
|
|
72996cd5e8 | ||
|
|
ab6ff1d2bd | ||
|
|
40f04580ec | ||
|
|
286e0f9c8f | ||
|
|
6aa71c3bd9 | ||
|
|
01a958b209 | ||
|
|
bbba8776ff | ||
|
|
34b6af632a | ||
|
|
99c593a8be | ||
|
|
57b130adbb | ||
|
|
558adb04ab | ||
|
|
684dd342d7 | ||
|
|
53bdafd2c5 | ||
|
|
f54f77ccaa | ||
|
|
6065205cb2 | ||
|
|
071a0c2b30 | ||
|
|
c4f9764556 | ||
|
|
99fe992d31 | ||
|
|
837016a417 | ||
|
|
d7dd250195 | ||
|
|
8626dfc79e | ||
|
|
75e23882bf | ||
|
|
95394c8e5a | ||
|
|
623d667fa0 | ||
|
|
7279227474 | ||
|
|
d2daea2927 | ||
|
|
f4493e59f9 | ||
|
|
9cca6ef2f9 | ||
|
|
aea6029ba1 | ||
|
|
fcc973cda6 | ||
|
|
0896a874c7 | ||
|
|
53ffb48e0a | ||
|
|
a70c3cfb54 | ||
|
|
1a4a6794e0 | ||
|
|
8024730027 | ||
|
|
211eb96eb6 | ||
|
|
5b7069c8b4 | ||
|
|
ece6aa1a79 | ||
|
|
185cfb9fe4 | ||
|
|
c8b2fee21c | ||
|
|
9ce56b757e | ||
|
|
72fc9ade82 | ||
|
|
05c85499bc | ||
|
|
3785a4d02c | ||
|
|
d74aaa326d | ||
|
|
9615c24fca | ||
|
|
783d711be1 | ||
|
|
30b3bf772b | ||
|
|
d69a74be22 | ||
|
|
908797e672 | ||
|
|
cf2267cff2 | ||
|
|
42ba6daf6d | ||
|
|
61b2963d0d | ||
|
|
c92d2d6430 | ||
|
|
274fa5cd84 | ||
|
|
baa07ce3f9 | ||
|
|
402a930af0 | ||
|
|
4475e2db1b | ||
|
|
2c12120713 | ||
|
|
84207a3f97 | ||
|
|
ab1c293818 | ||
|
|
3fbba94a0f | ||
|
|
a9b7fed072 | ||
|
|
ad196e2fe3 | ||
|
|
0c3b80fdbd | ||
|
|
c835eb9dfe | ||
|
|
99319c29a6 | ||
|
|
354c4f44b6 | ||
|
|
048ee7ba27 | ||
|
|
9eef10d3c3 | ||
|
|
ecdc3cd339 | ||
|
|
4f5b747c2b | ||
|
|
a0bc0851d6 | ||
|
|
c68c7b76d1 | ||
|
|
9590958aae | ||
|
|
d3199fcc60 | ||
|
|
4b45b28122 | ||
|
|
e458707966 | ||
|
|
3554b8ef0b | ||
|
|
48e7b27737 | ||
|
|
1cff207e67 | ||
|
|
aa50e5812b | ||
|
|
64cbfd2a0b | ||
|
|
e487303205 | ||
|
|
5a91148a37 | ||
|
|
6a56562120 | ||
|
|
8803fa8ccb | ||
|
|
90998a9b21 | ||
|
|
5e945d507e | ||
|
|
c1023f414f | ||
|
|
e737392fc4 | ||
|
|
01a09c9b8f | ||
|
|
a524b04f8c | ||
|
|
2332d39620 | ||
|
|
bc28dfedf8 | ||
|
|
09c0a1b41b | ||
|
|
b441c1bffe | ||
|
|
5be2a71a84 | ||
|
|
8766f77f24 | ||
|
|
e4beaad672 | ||
|
|
7f6056fc4c | ||
|
|
5ceb9b8906 | ||
|
|
2ace93e881 | ||
|
|
abd52a4ae2 | ||
|
|
76bccbd261 | ||
|
|
8f70de4d49 | ||
|
|
ea196f786d | ||
|
|
ced3b9dc53 | ||
|
|
5ca0595e4f | ||
|
|
53cd58a121 | ||
|
|
0a86f73869 | ||
|
|
12ba0a42b2 | ||
|
|
1ad3ffcf63 | ||
|
|
5f9a7ee0a2 | ||
|
|
b0c0255148 | ||
|
|
6b67c6a296 | ||
|
|
0017a6110f | ||
|
|
6bbb9ac512 | ||
|
|
6feb864e30 | ||
|
|
6ff04bf83d | ||
|
|
80778ddd25 | ||
|
|
c455e8bc75 | ||
|
|
411cffdeec | ||
|
|
04689c4138 | ||
|
|
50928fc1ef | ||
|
|
20c34a4312 | ||
|
|
fdd2634721 | ||
|
|
b043ac88e1 | ||
|
|
5c18914f2a | ||
|
|
a0e1ecb2ba | ||
|
|
5279ef3f96 | ||
|
|
36fb6e6877 | ||
|
|
6632db44ae | ||
|
|
613a5a19db | ||
|
|
21d63485b1 | ||
|
|
eaae1ae3fb | ||
|
|
333263b344 | ||
|
|
50db29c634 | ||
|
|
fe5c6c29e1 | ||
|
|
34d842901d | ||
|
|
a94833c482 | ||
|
|
0676ed3227 | ||
|
|
e12e480f79 | ||
|
|
3fa27e7464 | ||
|
|
013cbb7e1a | ||
|
|
97aee2acb0 | ||
|
|
43c2336d7f | ||
|
|
220677d76d | ||
|
|
0f396470ff | ||
|
|
94266c5111 | ||
|
|
0b3370f6fa | ||
|
|
c5abeccb65 | ||
|
|
aa7772b36c | ||
|
|
f47d84cf24 | ||
|
|
d97485cfc0 | ||
|
|
4fc4ac0c46 | ||
|
|
bd41fcfbe6 | ||
|
|
bd9623c892 | ||
|
|
00e65b239c | ||
|
|
b654a0fbd3 | ||
|
|
2f757d249d | ||
|
|
db33f31dc1 | ||
|
|
661dcdda07 | ||
|
|
22a65f7666 | ||
|
|
1ce35da941 | ||
|
|
e6cffd9add | ||
|
|
213a00ec5e | ||
|
|
c03c057a42 | ||
|
|
73849713e8 | ||
|
|
0610a4e156 | ||
|
|
29efaadf0a | ||
|
|
02ba85f8e0 | ||
|
|
d563b3ecb0 | ||
|
|
ce0ab6b836 | ||
|
|
feedb0808b | ||
|
|
c14737f39c | ||
|
|
4b6375a4a4 | ||
|
|
bfa1af2101 | ||
|
|
a866e257fd | ||
|
|
d34656475e | ||
|
|
2b1edeceb4 | ||
|
|
f49d1247d2 | ||
|
|
ee697391d6 | ||
|
|
93c02c012f | ||
|
|
545258bd26 | ||
|
|
9611ecf356 | ||
|
|
0887e9a6de | ||
|
|
a2086298f6 | ||
|
|
b7c88467e2 | ||
|
|
0c997dbe85 | ||
|
|
6d3265a7fb | ||
|
|
a46092a90a | ||
|
|
25da342f75 | ||
|
|
c3160aea0a | ||
|
|
7bbc240cae | ||
|
|
1958e11f45 | ||
|
|
738a11dcdc | ||
|
|
280bc617d0 | ||
|
|
252def6bab | ||
|
|
4361f071e8 | ||
|
|
7ef8099916 | ||
|
|
1558b44495 | ||
|
|
0c42ea97a4 | ||
|
|
51f2a45217 | ||
|
|
3b0ff1d7ca | ||
|
|
62dea1454d | ||
|
|
b5f8137499 | ||
|
|
e64268427d | ||
|
|
99ee15c731 | ||
|
|
dfa392edb7 | ||
|
|
7075847ef4 | ||
|
|
19da0a2068 | ||
|
|
180339f16b | ||
|
|
c86afd1a5c | ||
|
|
910a42d647 | ||
|
|
18abe7d9e1 | ||
|
|
ae5338bde5 | ||
|
|
7843001aa7 | ||
|
|
cff19ec212 | ||
|
|
c126e40795 | ||
|
|
11c4d7311b | ||
|
|
1f2b1f5880 | ||
|
|
14f9ba5c3f | ||
|
|
26183926a3 | ||
|
|
a7a3c52c88 | ||
|
|
350997b03c | ||
|
|
48c6e2248a | ||
|
|
08fcf381e8 | ||
|
|
f3f78303b1 | ||
|
|
555bc46d14 | ||
|
|
b14f68378d | ||
|
|
8553460afe | ||
|
|
16cf97584c | ||
|
|
a5680759eb | ||
|
|
b6e073d03c | ||
|
|
d7752ebd8b | ||
|
|
fdc9364062 | ||
|
|
da47929b6a | ||
|
|
3f663e7a4e | ||
|
|
3453f63787 | ||
|
|
8cd46388e5 | ||
|
|
5f819dc68a | ||
|
|
14aa9eaa39 | ||
|
|
c0585278d0 | ||
|
|
d9a36a889e | ||
|
|
788e80ce39 | ||
|
|
68b31dddd5 | ||
|
|
f0d9fc7bce | ||
|
|
684e85cc5e | ||
|
|
d45be919cd | ||
|
|
5c3bd1b19f | ||
|
|
600e8dd3c8 | ||
|
|
08764d5bbc | ||
|
|
749387bbfa | ||
|
|
88bb908c76 | ||
|
|
d260dda29e | ||
|
|
a8362c1a70 | ||
|
|
87fa294a42 | ||
|
|
330c46cdb2 | ||
|
|
27f4b56e71 | ||
|
|
2262bc18fe | ||
|
|
bc0e688f96 | ||
|
|
2fb02c57b6 | ||
|
|
bf0f360935 | ||
|
|
6976865176 | ||
|
|
c862b89079 | ||
|
|
6a15977238 | ||
|
|
7d6468f70b | ||
|
|
ed9a351518 | ||
|
|
d4b3e0ad62 | ||
|
|
1bd2d3d992 | ||
|
|
ce452d5759 | ||
|
|
56cb24bd0d | ||
|
|
c7b46b71a0 | ||
|
|
e7e6b98958 | ||
|
|
2f27b48f7b | ||
|
|
04a501edb7 | ||
|
|
01f07fb952 | ||
|
|
6680827faf | ||
|
|
7699c38b99 | ||
|
|
aa265352ff | ||
|
|
56e5e66f86 | ||
|
|
753364bbff | ||
|
|
8fbb28cc6f | ||
|
|
066ba95737 | ||
|
|
1b9789937f |
@@ -10,8 +10,11 @@
|
||||
init
|
||||
build/hyper_daemon
|
||||
build/hyper-initrd.img
|
||||
build/cbfs.rom
|
||||
build/root/*
|
||||
build/*iso
|
||||
build/daemon
|
||||
build/kernel_config.old
|
||||
build/.*
|
||||
src/.*
|
||||
Makefile
|
||||
|
||||
@@ -1 +1,8 @@
|
||||
SUBDIRS=src build
|
||||
|
||||
initrd-local:
|
||||
@echo finish make initrd
|
||||
cbfs-local:
|
||||
@echo finish make cbfs
|
||||
kernel-local:
|
||||
@echo finish make kernel
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
# The init Task for Hyper
|
||||
# The init Task for HyperContainer
|
||||
|
||||
You can get binary installer of Hyper and HyperStart through [The Hyper Page](https://github.com/hyperhq/hyper)
|
||||
You can get the binary installer of HyperContainer and HyperStart through [The Hyper Page](https://github.com/hyperhq/hyperd)
|
||||
|
||||
## Build from source
|
||||
|
||||
clone this repo, and make sure have build-essentials installed. Go into the working copy and
|
||||
clone this repo, and make sure you have build-essentials installed. Go into the working copy and
|
||||
|
||||
> ./autogen.sh
|
||||
> ./configure
|
||||
> make
|
||||
|
||||
Then you can find `hyper-initrd.img` in build directory, together with a pre-build kernel.
|
||||
Then you can find `hyper-initrd.img` in the build directory, together with a pre-built kernel.
|
||||
|
||||
If you want to get the boot disk file for VirtualBox, please reconfigure with flag --with-vbox,
|
||||
|
||||
> ./configure --with-vbox
|
||||
> make
|
||||
|
||||
Then you can find `hyper-vbox-bootimage.iso` in the build directory. Booting from this iso will
|
||||
bring you to the hyper world.
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
FROM centos:7
|
||||
MAINTAINER Hyper Developers <dev@hyper.sh>
|
||||
|
||||
RUN yum install -y patch gcc ncurses-devel make openssl-devel bc
|
||||
|
||||
ENV KERNEL_VERSION 4.4.12
|
||||
ENV LOCALVERSION -hyper
|
||||
ENV KERNEL_RELEASE ${KERNEL_VERSION}${LOCALVERSION}
|
||||
|
||||
ENV KBUILD_BUILD_USER dev
|
||||
ENV KBUILD_BUILD_HOST hyper.sh
|
||||
ENV KBUILD_BUILD_VERSION 1
|
||||
|
||||
RUN mkdir /root/build/ && mkdir /root/build/result/
|
||||
RUN curl -fSL https://cdn.kernel.org/pub/linux/kernel/v4.x/linux-${KERNEL_VERSION}.tar.gz | tar -zx -C /root/build
|
||||
|
||||
COPY kernel_config /root/build/linux-${KERNEL_VERSION}/.config
|
||||
COPY kernel_patch/ /root/build/kernel_patch/
|
||||
|
||||
RUN cd /root/build/linux-${KERNEL_VERSION}/ && for patch in /root/build/kernel_patch/*.patch; do patch -p1 <$patch || exit 1; done
|
||||
RUN cd /root/build/linux-${KERNEL_VERSION}/ && make silentoldconfig && make -j 8
|
||||
|
||||
# install to /root/build/result/ so that we can get them from it
|
||||
RUN cp /root/build/linux-${KERNEL_VERSION}/arch/x86_64/boot/bzImage /root/build/result/kernel
|
||||
RUN mkdir /root/build/result/modules &&\
|
||||
cd /root/build/linux-${KERNEL_VERSION}/ && make modules_install INSTALL_MOD_PATH="/root/build/result/modules" &&\
|
||||
cd /root/build/result/modules/lib/modules/ && rm -f ${KERNEL_RELEASE}/{build,source} &&\
|
||||
tar -cf /root/build/result/modules.tar ${KERNEL_RELEASE}/ && rm -rf /root/build/result/modules
|
||||
RUN cp /root/build/linux-${KERNEL_VERSION}/.config /root/build/result/kernel_config
|
||||
+15
-3
@@ -1,7 +1,19 @@
|
||||
bin_PROGRAMS=hyper_daemon
|
||||
hyper_daemon_SOURCES=hyper_daemon.c ../src/net.c
|
||||
all-local:
|
||||
all-local: initrd
|
||||
|
||||
if WITH_VBOX
|
||||
initrd-local:
|
||||
bash ./make-initrd.sh vbox
|
||||
else
|
||||
initrd-local:
|
||||
bash ./make-initrd.sh
|
||||
endif
|
||||
|
||||
cbfs-local:
|
||||
bash ./make-initrd.sh cbfs
|
||||
|
||||
kernel-local:
|
||||
hyperctl build -t hyperstart-dev:latest .
|
||||
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/kernel >kernel.new && mv -f kernel.new kernel
|
||||
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/modules.tar >modules.tar
|
||||
mv kernel_config kernel_config.old
|
||||
hyperctl run --rm hyperstart-dev:latest cat /root/build/result/kernel_config >kernel_config
|
||||
|
||||
Executable
BIN
Binary file not shown.
@@ -1,168 +0,0 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
#include <linux/un.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../src/hyper.h"
|
||||
#include "../src/net.h"
|
||||
|
||||
int test_sendmsg(int fd, unsigned int type, unsigned int len, char *message)
|
||||
{
|
||||
uint8_t buf[4096];
|
||||
|
||||
|
||||
/* send hyper info to guest */
|
||||
hyper_set_be32(buf, type);
|
||||
|
||||
len += 8;
|
||||
|
||||
fprintf(stdout, "type is %u, len is %u\n", type, len);
|
||||
hyper_set_be32(buf + 4, len);
|
||||
|
||||
if (message)
|
||||
memcpy(buf + 8, message, len - 8);
|
||||
|
||||
if (write(fd, buf, len) != len) {
|
||||
fprintf(stderr, "send SETDVM MESSAGE failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "finish sending\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
int test_sendmsg_from_file(int fd, unsigned int type, char *file)
|
||||
{
|
||||
int file_fd = open(file, O_RDONLY);
|
||||
uint8_t buf[4096];
|
||||
unsigned int len = 0;
|
||||
|
||||
if (file_fd < 0) {
|
||||
perror("fail to open file");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (len < 4096) {
|
||||
int size = read(file_fd, buf + len, sizeof(buf) - len);
|
||||
|
||||
fprintf(stdout, "read %d data\n", size);
|
||||
if (size < 0) {
|
||||
perror("fail to read data");
|
||||
return -1;
|
||||
} else if (size == 0) {
|
||||
/* buf[len] = '\0';*/
|
||||
fprintf(stdout, "get buf %s, call sendmsg\n", buf);
|
||||
test_sendmsg(fd, type, len, (char *)buf);
|
||||
break;
|
||||
}
|
||||
|
||||
len += size;
|
||||
}
|
||||
|
||||
close(file_fd);
|
||||
|
||||
if (read(fd, buf, 8) != 8) {
|
||||
fprintf(stderr, "read response failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
type = hyper_get_be32(buf);
|
||||
if (type != ACK) {
|
||||
fprintf(stderr, "incorrect type %d\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int sock, fd = -1;
|
||||
struct sockaddr_un addr;
|
||||
uint8_t buf[8];
|
||||
unsigned int type;
|
||||
|
||||
unlink("/tmp/hyper.sock");
|
||||
|
||||
sock = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0);
|
||||
if (sock == -1) {
|
||||
perror("create unix socket failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
addr.sun_family = AF_UNIX;
|
||||
strncpy(addr.sun_path, "/tmp/hyper.sock", UNIX_PATH_MAX);
|
||||
addr.sun_path[UNIX_PATH_MAX - 1] = '\0';
|
||||
|
||||
if (bind(sock, ((struct sockaddr *) &addr), sizeof(addr)) == -1) {
|
||||
perror("bind failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (listen(sock, 1) == -1) {
|
||||
perror("bind failed");
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (fd == -1)
|
||||
fd = accept4(sock, NULL, NULL, SOCK_CLOEXEC);
|
||||
|
||||
fprintf(stdout, "connected\n");
|
||||
if (read(fd, buf, 8) != 8) {
|
||||
fprintf(stderr, "read failed, buf %s\n", buf);
|
||||
goto out1;
|
||||
}
|
||||
|
||||
type = hyper_get_be32(buf);
|
||||
fprintf(stdout, "get type %d\n", type);
|
||||
|
||||
if (type != READY) {
|
||||
fprintf(stderr, "incorrect type %d\n", type);
|
||||
goto out1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "get length %d\n", hyper_get_be32(buf + 4));
|
||||
|
||||
/* test_sendmsg_from_file(fd, SETDVM, "sethyper.json"); */
|
||||
if (test_sendmsg_from_file(fd, STARTPOD, "startpod.json") < 0) {
|
||||
fprintf(stderr, "send startpod message failed\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (test_sendmsg_from_file(fd, EXECCMD, "execcmd.json") < 0) {
|
||||
fprintf(stderr, "send execcmd message failed\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (test_sendmsg(fd, STOPPOD, 0, NULL) < 0) {
|
||||
fprintf(stderr, "send stoppod message failed\n");
|
||||
goto out1;
|
||||
}
|
||||
|
||||
if (read(fd, buf, 8) != 8) {
|
||||
fprintf(stderr, "read response failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
type = hyper_get_be32(buf);
|
||||
if (type != ACK) {
|
||||
fprintf(stderr, "incorrect type %d\n", type);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (read(fd, buf, 8) != 8) {
|
||||
fprintf(stderr, "read response failed\n");
|
||||
return -1;
|
||||
}
|
||||
out1:
|
||||
close(fd);
|
||||
out:
|
||||
close(sock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
Executable
BIN
Binary file not shown.
Binary file not shown.
+918
-177
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.
+56
-18
@@ -1,40 +1,78 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -rf root
|
||||
mkdir root
|
||||
rm -rf /tmp/hyperstart-rootfs
|
||||
mkdir -p /tmp/hyperstart-rootfs/lib /tmp/hyperstart-rootfs/lib64 /tmp/hyperstart-rootfs/lib/modules
|
||||
|
||||
cp ../src/init ./root
|
||||
cp ../src/init /tmp/hyperstart-rootfs
|
||||
cp busybox /tmp/hyperstart-rootfs
|
||||
cp iptables /tmp/hyperstart-rootfs
|
||||
cp libm.so.6 /tmp/hyperstart-rootfs/lib64/
|
||||
tar -xf modules.tar -C /tmp/hyperstart-rootfs/lib/modules
|
||||
|
||||
ldd ./root/init | while read line
|
||||
ldd /tmp/hyperstart-rootfs/init | while read line
|
||||
do
|
||||
arr=(${line// / })
|
||||
|
||||
for lib in ${arr[@]}
|
||||
do
|
||||
if [ "${lib:0:1}" = "/" ]; then
|
||||
dir=root`dirname $lib`
|
||||
dir=/tmp/hyperstart-rootfs`dirname $lib`
|
||||
mkdir -p "${dir}"
|
||||
cp -f $lib $dir
|
||||
fi
|
||||
done
|
||||
done
|
||||
cd ./root && find . | cpio -H newc -o | gzip -9 > ../hyper-initrd.img
|
||||
|
||||
if [ "$1"x = "vbox"x ]; then
|
||||
echo "build initrd for vbox"
|
||||
cp ./vbox/driver/* /tmp/hyperstart-rootfs
|
||||
fi
|
||||
|
||||
if [ "$1" != "cbfs" ]; then
|
||||
( cd /tmp/hyperstart-rootfs && find . | cpio -H newc -o | gzip -9 ) > ./hyper-initrd.img
|
||||
|
||||
cd ../
|
||||
rm -rf /tmp/hyperstart-rootfs
|
||||
|
||||
if [ "$1"x = "cbfs"x ]; then
|
||||
echo "build cbfs"
|
||||
rm -rf .cbfs
|
||||
rm -rf cbfs.rom
|
||||
|
||||
mkdir .cbfs
|
||||
dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1
|
||||
cbfstool .cbfs/cbfs.rom create -s 8128k -B .cbfs/boot.bin -m x86 0x1000
|
||||
cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw
|
||||
cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw
|
||||
echo 'console=ttyS0 panic=1 no_timer_check' > .cbfs/cmdline
|
||||
cbfstool .cbfs/cbfs.rom add -f .cbfs/cmdline -n cmdline -t raw
|
||||
cp .cbfs/cbfs.rom ./
|
||||
rm -rf .cbfs
|
||||
exit 0
|
||||
fi
|
||||
|
||||
cd ../
|
||||
if [ "$1"x = "vbox"x ]; then
|
||||
mkdir tmp
|
||||
mkdir -p tmp/images
|
||||
mkdir -p tmp/kernel
|
||||
mkdir -p tmp/isolinux
|
||||
|
||||
echo "build cbfs"
|
||||
rm -rf .cbfs
|
||||
rm -rf cbfs.rom
|
||||
cd tmp
|
||||
cp ../vbox/kernel ./kernel/
|
||||
cp ../hyper-initrd.img ./images/initrd.img
|
||||
cp ../vbox/isolinux/isolinux.bin ./isolinux/
|
||||
cp ../vbox/isolinux/ldlinux.c32 ./isolinux/
|
||||
|
||||
mkdir .cbfs
|
||||
dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1
|
||||
cbfstool .cbfs/cbfs.rom create -s 4096k -B .cbfs/boot.bin -m x86 0x1000
|
||||
cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw
|
||||
cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw
|
||||
cp .cbfs/cbfs.rom ./
|
||||
rm -rf .cbfs
|
||||
cat > isolinux/syslinux.cfg <<EOF
|
||||
DEFAULT linux
|
||||
LABEL linux
|
||||
SAY Now booting the kernel from SYSLINUX...
|
||||
KERNEL /kernel/kernel
|
||||
APPEND initrd=/images/initrd.img
|
||||
EOF
|
||||
|
||||
cd ../
|
||||
|
||||
mkisofs -o hyper-vbox-boot.iso -b isolinux/isolinux.bin -c isolinux/boot.cat -no-emul-boot -boot-load-size 4 -boot-info-table tmp
|
||||
|
||||
rm -fr tmp
|
||||
fi
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Executable
BIN
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
+12
-10
@@ -2,9 +2,9 @@
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
AC_PREREQ([2.69])
|
||||
AC_INIT([hyperstart], [0.1], [www.hyper.sh])
|
||||
AC_INIT([hyperstart], [0.6.2], [www.hyper.sh])
|
||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||
AM_EXTRA_RECURSIVE_TARGETS([cbfs])
|
||||
AM_EXTRA_RECURSIVE_TARGETS([initrd cbfs kernel])
|
||||
AC_CONFIG_SRCDIR([src/init.c])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
|
||||
@@ -32,20 +32,22 @@ AC_TYPE_UINT8_T
|
||||
# Checks for library functions.
|
||||
AC_FUNC_FORK
|
||||
AC_CHECK_FUNCS([dup2 memmove memset mkdir setenv socket strchr strdup strrchr strtoul], [fail=0], [fail=1])
|
||||
AC_CHECK_FUNCS([setns])
|
||||
|
||||
if test "$fail" = "1" ; then
|
||||
AC_MSG_ERROR(Unable to find necessary functions)
|
||||
fi
|
||||
|
||||
AC_ARG_WITH([ttys],
|
||||
[AS_HELP_STRING([--with-ttys],
|
||||
[use pci serial device as container tty])],
|
||||
[],[with_ttys=yes])
|
||||
AC_ARG_WITH([vbox],
|
||||
[AS_HELP_STRING([--with-vbox],
|
||||
[run hyperstart on Virtualbox])],
|
||||
[],[with_vbox=no])
|
||||
|
||||
if test "x$with_ttys" != "xno" ; then
|
||||
AC_DEFINE_UNQUOTED([WITH_TTYS], 1, [where use pci serial device as container tty])
|
||||
if test "x$with_vbox" != "xno" ; then
|
||||
AC_DEFINE_UNQUOTED([WITH_VBOX], 1, [run hyperstart on Virtualbox])
|
||||
fi
|
||||
AM_CONDITIONAL([WITH_TTYS], [test "x$with_ttys" != "xno"])
|
||||
|
||||
AM_CONDITIONAL([WITH_VBOX], [test "x$with_vbox" != "xno"])
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
@@ -58,7 +60,7 @@ AC_MSG_RESULT([
|
||||
${PACKAGE} ${VERSION}
|
||||
prefix: ${prefix}
|
||||
|
||||
with-ttys: ${with_ttys}
|
||||
with-vbox: ${with_vbox}
|
||||
|
||||
compiler: ${CC}
|
||||
cflags: ${CFLAGS}
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
AM_CFLAGS = -Wall
|
||||
bin_PROGRAMS=init
|
||||
init_SOURCES=init.c jsmn.c net.c util.c parse.c container.c exec.c event.c
|
||||
init_SOURCES=init.c jsmn.c net.c util.c parse.c parson.c container.c exec.c event.c portmapping.c
|
||||
|
||||
+510
-264
@@ -7,6 +7,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <unistd.h>
|
||||
#include <mntent.h>
|
||||
#include <signal.h>
|
||||
@@ -16,18 +17,79 @@
|
||||
|
||||
#include "util.h"
|
||||
#include "hyper.h"
|
||||
#include "parse.h"
|
||||
#include "syscall.h"
|
||||
|
||||
static int container_setup_env(struct hyper_container *container)
|
||||
static int container_populate_volume(char *src, char *dest)
|
||||
{
|
||||
int i;
|
||||
struct env *env;
|
||||
struct stat st;
|
||||
|
||||
for (i = 0; i < container->envs_num; i++) {
|
||||
env = &container->envs[i];
|
||||
fprintf(stdout, "populate volumes from %s to %s\n", src, dest);
|
||||
/* FIXME: check if has data in volume, (except lost+found) */
|
||||
|
||||
setenv(env->env, env->value, 1);
|
||||
if (stat(dest, &st) == 0) {
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
fprintf(stderr, "the _data in volume %s is not directroy\n", dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (errno != ENOENT) {
|
||||
perror("access to volume failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hyper_mkdir(dest, 0777) < 0) {
|
||||
fprintf(stderr, "fail to create directroy %s\n", dest);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hyper_copy_dir(src, dest);
|
||||
}
|
||||
|
||||
const char *INIT_VOLUME_FILENAME = ".hyper_file_volume_data_do_not_create_on_your_own";
|
||||
|
||||
static int container_check_file_volume(char *hyper_path, const char **filename)
|
||||
{
|
||||
struct dirent **list;
|
||||
struct stat stbuf;
|
||||
int i, num, found = 0;
|
||||
char path[PATH_MAX];
|
||||
|
||||
*filename = NULL;
|
||||
num = scandir(hyper_path, &list, NULL, NULL);
|
||||
if (num < 0) {
|
||||
/* No data in the volume yet, treat as non-file-volume */
|
||||
if (errno == ENOENT) {
|
||||
return 0;
|
||||
}
|
||||
perror("scan path failed");
|
||||
return -1;
|
||||
} else if (num != 3) {
|
||||
fprintf(stdout, "%s has %d files/dirs\n", hyper_path, num - 2);
|
||||
for (i = 0; i < num; i++) {
|
||||
free(list[i]);
|
||||
}
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
sprintf(path, "%s/%s", hyper_path, INIT_VOLUME_FILENAME);
|
||||
for (i = 0; i < num; i++) {
|
||||
if (strcmp(list[i]->d_name, ".") != 0 &&
|
||||
strcmp(list[i]->d_name, "..") != 0 &&
|
||||
strcmp(list[i]->d_name, INIT_VOLUME_FILENAME) == 0 &&
|
||||
stat(path, &stbuf) == 0 && S_ISREG(stbuf.st_mode)) {
|
||||
found++;
|
||||
}
|
||||
free(list[i]);
|
||||
}
|
||||
free(list);
|
||||
|
||||
fprintf(stdout, "%s %s a file volume\n", hyper_path, found > 0?"is":"is not");
|
||||
*filename = found > 0 ? INIT_VOLUME_FILENAME : NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -38,121 +100,113 @@ static int container_setup_volume(struct hyper_container *container)
|
||||
struct volume *vol;
|
||||
|
||||
for (i = 0; i < container->vols_num; i++) {
|
||||
char volume[512];
|
||||
char mountpoint[512];
|
||||
char *options = NULL;
|
||||
const char *filevolume = NULL;
|
||||
vol = &container->vols[i];
|
||||
|
||||
sprintf(dev, "/.oldroot/dev/%s", vol->device);
|
||||
if (vol->scsiaddr)
|
||||
hyper_find_sd(vol->scsiaddr, &vol->device);
|
||||
|
||||
sprintf(dev, "/dev/%s", vol->device);
|
||||
sprintf(path, "/tmp/%s", vol->mountpoint);
|
||||
fprintf(stdout, "mount %s to %s\n", dev, vol->mountpoint);
|
||||
sprintf(mountpoint, "./%s", vol->mountpoint);
|
||||
|
||||
if (hyper_mkdir(path) < 0 || hyper_mkdir(vol->mountpoint) < 0) {
|
||||
fprintf(stdout, "mountpoint %s\n", vol->mountpoint);
|
||||
fprintf(stdout, "mount %s to %s, tmp path %s\n",
|
||||
dev, vol->mountpoint, path);
|
||||
|
||||
if (hyper_mkdir(path, 0755) < 0) {
|
||||
perror("create volume dir failed");
|
||||
continue;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(dev, path, vol->fstype, 0, NULL) < 0) {
|
||||
perror("mount volume device faled");
|
||||
continue;
|
||||
if (!strncmp(vol->fstype, "xfs", strlen("xfs")))
|
||||
options = "nouuid";
|
||||
|
||||
if (mount(dev, path, vol->fstype, 0, options) < 0) {
|
||||
perror("mount volume device failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount volume device faled");
|
||||
continue;
|
||||
sprintf(volume, "/%s/_data", path);
|
||||
if (container_check_file_volume(volume, &filevolume) < 0)
|
||||
return -1;
|
||||
|
||||
if (filevolume == NULL) {
|
||||
if (hyper_mkdir(mountpoint, 0755) < 0) {
|
||||
perror("create volume dir failed");
|
||||
return -1;
|
||||
}
|
||||
if (vol->docker) {
|
||||
if (container->initialize &&
|
||||
(container_populate_volume(mountpoint, volume) < 0)) {
|
||||
fprintf(stderr, "fail to populate volume %s\n", mountpoint);
|
||||
return -1;
|
||||
}
|
||||
} else if (hyper_mkdir(volume, 0777) < 0) {
|
||||
/* First time mounting an empty volume */
|
||||
perror("create _data dir failed");
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
hyper_filize(mountpoint);
|
||||
if (hyper_create_file(mountpoint) < 0) {
|
||||
perror("create volume file failed");
|
||||
return -1;
|
||||
}
|
||||
sprintf(volume, "/%s/_data/%s", path, filevolume);
|
||||
/* 0777 so that any user can read/write the new file volume */
|
||||
if (chmod(volume, 0777) < 0) {
|
||||
fprintf(stderr, "fail to chmod directroy %s\n", volume);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (mount(volume, mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount volume device failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (vol->readonly &&
|
||||
mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
||||
perror("mount fsmap faled");
|
||||
mount(volume, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
||||
perror("mount fsmap failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
umount(path);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void container_unmount_oldroot(char *path)
|
||||
{
|
||||
FILE *mtab;
|
||||
struct mntent *mnt;
|
||||
char *mntlist[128];
|
||||
int i;
|
||||
int n = 0;
|
||||
char *filesys;
|
||||
|
||||
mtab = setmntent("/proc/mounts", "r");
|
||||
if (mtab == NULL) {
|
||||
fprintf(stderr, "cannot open /proc/mount");
|
||||
return;
|
||||
}
|
||||
|
||||
while (n < 128 && (mnt = getmntent(mtab))) {
|
||||
if (strncmp(mnt->mnt_dir, path, strlen(path)))
|
||||
continue;
|
||||
mntlist[n++] = strdup(mnt->mnt_dir);
|
||||
}
|
||||
|
||||
endmntent(mtab);
|
||||
|
||||
for (i = n - 1; i >= 0; i--) {
|
||||
filesys = mntlist[i];
|
||||
fprintf(stdout, "umount %s\n", filesys);
|
||||
if (umount(mntlist[i]) < 0 && umount2(mntlist[i],
|
||||
MNT_DETACH) < 0) {
|
||||
fprintf(stdout, "umount %s: %s failed\n",
|
||||
filesys, strerror(errno));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int container_setup_mount(struct hyper_container *container)
|
||||
{
|
||||
int i, fd;
|
||||
char src[512];
|
||||
struct fsmap *map;
|
||||
|
||||
if (mount("proc", "/proc", "proc", 0, NULL) < 0 ||
|
||||
mount("sysfs", "/sys", "sysfs", 0, NULL) < 0 ||
|
||||
mount("devtmpfs", "/dev", "devtmpfs", 0, NULL) < 0) {
|
||||
perror("mount basic filesystem for container failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hyper_mkdir("/dev/pts") < 0) {
|
||||
fprintf(stderr, "create /dev/pts failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sprintf(src, "/.oldroot/tmp/hyper/%s/devpts", container->id) < 0) {
|
||||
fprintf(stderr, "get container devpts failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(src, "/dev/pts/", NULL, MS_BIND, NULL) < 0) {
|
||||
perror("move pts to /dev/pts failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink("/dev/ptmx") < 0)
|
||||
perror("remove /dev/ptmx failed");
|
||||
if (symlink("/dev/pts/ptmx", "/dev/ptmx") < 0)
|
||||
perror("link /dev/pts/ptmx to /dev/ptmx failed");
|
||||
|
||||
for (i = 0; i < container->maps_num; i++) {
|
||||
struct stat st;
|
||||
char *src, path[512], volume[512];
|
||||
struct fsmap *map = &container->maps[i];
|
||||
char mountpoint[512];
|
||||
|
||||
map = &container->maps[i];
|
||||
|
||||
sprintf(src, "/.oldroot/tmp/hyper/shared/%s", map->source);
|
||||
fprintf(stdout, "mount %s to %s\n", src, map->path);
|
||||
sprintf(path, "/tmp/hyper/shared/%s", map->source);
|
||||
sprintf(mountpoint, "./%s", map->path);
|
||||
fprintf(stdout, "mount %s to %s\n", path, mountpoint);
|
||||
|
||||
src = path;
|
||||
stat(src, &st);
|
||||
|
||||
if (st.st_mode & S_IFDIR) {
|
||||
if (hyper_mkdir(map->path) < 0) {
|
||||
if (hyper_mkdir(mountpoint, 0755) < 0) {
|
||||
perror("create map dir failed");
|
||||
continue;
|
||||
}
|
||||
if (map->docker) {
|
||||
/* converted from volume */
|
||||
sprintf(volume, "%s/_data", path);
|
||||
src = volume;
|
||||
if (container->initialize &&
|
||||
(container_populate_volume(mountpoint, volume) < 0)) {
|
||||
fprintf(stderr, "fail to populate volume %s\n", mountpoint);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fd = open(map->path, O_CREAT|O_WRONLY, 0755);
|
||||
int fd = open(mountpoint, O_CREAT|O_WRONLY, 0755);
|
||||
if (fd < 0) {
|
||||
perror("create map file failed");
|
||||
continue;
|
||||
@@ -160,16 +214,224 @@ static int container_setup_mount(struct hyper_container *container)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
if (mount(src, map->path, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount fsmap faled");
|
||||
if (mount(src, mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount fsmap failed");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (map->readonly == 0)
|
||||
continue;
|
||||
|
||||
if (mount(src, map->path, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
||||
perror("mount fsmap faled");
|
||||
if (mount(src, mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
||||
perror("mount fsmap failed");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_setup_modules(struct hyper_container *container)
|
||||
{
|
||||
struct stat st;
|
||||
struct utsname uts;
|
||||
char src[512], dst[512];
|
||||
|
||||
if (uname(&uts) < 0) {
|
||||
perror("fail to call uname");
|
||||
return -1;
|
||||
}
|
||||
|
||||
sprintf(src, "/lib/modules/%s", uts.release);
|
||||
sprintf(dst, "./%s", src);
|
||||
|
||||
if (stat(dst, &st) == 0) {
|
||||
struct dirent **list;
|
||||
int num;
|
||||
|
||||
if (!S_ISDIR(st.st_mode)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
num = scandir(dst, &list, NULL, NULL);
|
||||
if (num > 2) {
|
||||
fprintf(stdout, "%s is not null, %d", dst, num);
|
||||
return 0;
|
||||
}
|
||||
} else if (errno == ENOENT) {
|
||||
if (hyper_mkdir(dst, 0755) < 0)
|
||||
return -1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(src, dst, NULL, MS_BIND, NULL) < 0) {
|
||||
perror("mount bind modules failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_setup_mount(struct hyper_container *container)
|
||||
{
|
||||
char src[512];
|
||||
|
||||
// current dir is container rootfs, the operations on "./PATH" are the operations on container's "/PATH"
|
||||
hyper_mkdir("./proc", 0755);
|
||||
hyper_mkdir("./sys", 0755);
|
||||
hyper_mkdir("./dev", 0755);
|
||||
hyper_mkdir("./lib/modules", 0755);
|
||||
|
||||
if (mount("proc", "./proc", "proc", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
|
||||
mount("sysfs", "./sys", "sysfs", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
|
||||
mount("devtmpfs", "./dev", "devtmpfs", MS_NOSUID, NULL) < 0) {
|
||||
perror("mount basic filesystem for container failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hyper_mkdir("./dev/shm", 0755) < 0) {
|
||||
fprintf(stderr, "create /dev/shm failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("tmpfs", "./dev/shm/", "tmpfs", MS_NOSUID| MS_NODEV, NULL) < 0) {
|
||||
perror("mount shm failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hyper_mkdir("./dev/pts", 0755) < 0) {
|
||||
fprintf(stderr, "create /dev/pts failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sprintf(src, "/tmp/hyper/%s/devpts", container->id) < 0) {
|
||||
fprintf(stderr, "get container devpts failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount(src, "./dev/pts/", NULL, MS_BIND, NULL) < 0) {
|
||||
perror("move pts to /dev/pts failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (unlink("./dev/ptmx") < 0)
|
||||
perror("remove /dev/ptmx failed");
|
||||
if (symlink("/dev/pts/ptmx", "./dev/ptmx") < 0)
|
||||
perror("link /dev/pts/ptmx to /dev/ptmx failed");
|
||||
|
||||
symlink("/proc/self/fd", "./dev/fd");
|
||||
symlink("/proc/self/fd/0", "./dev/stdin");
|
||||
symlink("/proc/self/fd/1", "./dev/stdout");
|
||||
symlink("/proc/self/fd/2", "./dev/stderr");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_recreate_file(char *filename)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
fprintf(stdout, "recreate file %s\n", filename);
|
||||
if (stat(filename, &stbuf) < 0) {
|
||||
if (errno != ENOENT) {
|
||||
fprintf(stderr, "failed to stat %s: %d\n", filename, errno);
|
||||
return -1;
|
||||
}
|
||||
return hyper_create(filename);
|
||||
}
|
||||
if (stbuf.st_mode & S_IFREG && stbuf.st_size == 0)
|
||||
return 0;
|
||||
|
||||
hyper_unlink(filename);
|
||||
return hyper_create(filename);
|
||||
}
|
||||
|
||||
static int container_recreate_symlink(char *oldpath, char *newpath)
|
||||
{
|
||||
fprintf(stdout, "recreate symlink %s to %s\n", newpath, oldpath);
|
||||
hyper_unlink(newpath);
|
||||
return hyper_symlink(oldpath, newpath);
|
||||
}
|
||||
|
||||
/*
|
||||
* Docker uses the init layer to protect against unwanted side effects on
|
||||
* the rw layer. We recreate the same files here to have similar effect.
|
||||
* Docker also creates directories like /dev/pts, /dev/shm, /proc, /sys,
|
||||
* which we have over ridden in container_setup_mount, so no need to create
|
||||
* them here.
|
||||
*/
|
||||
static int container_setup_init_layer(struct hyper_container *container,
|
||||
int setup_dns)
|
||||
{
|
||||
if (!container->initialize)
|
||||
return 0;
|
||||
|
||||
hyper_mkdir("./etc/", 0755);
|
||||
|
||||
if (setup_dns && container_recreate_file("./etc/resolv.conf") < 0)
|
||||
return -1;
|
||||
|
||||
if (container_recreate_file("./etc/hosts") < 0)
|
||||
return -1;
|
||||
|
||||
if (container_recreate_file("./etc/hostname") < 0)
|
||||
return -1;
|
||||
|
||||
if (container_recreate_symlink("/proc/mounts", "./etc/mtab") < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_setup_sysctl(struct hyper_container *container)
|
||||
{
|
||||
int i;
|
||||
struct sysctl *sys;
|
||||
|
||||
for (i = 0; i < container->sys_num; i++) {
|
||||
char path[256];
|
||||
|
||||
sys = &container->sys[i];
|
||||
|
||||
sprintf(path, "/proc/sys/%s", sys->path);
|
||||
fprintf(stdout, "sysctl %s value %s\n", sys->path, sys->value);
|
||||
|
||||
if (hyper_write_file(path, sys->value, strlen(sys->value)) < 0) {
|
||||
fprintf(stderr, "sysctl: write %s to %s failed\n", sys->value, path);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_setup_dns(struct hyper_container *container)
|
||||
{
|
||||
int fd;
|
||||
struct stat st;
|
||||
char *src = "/tmp/hyper/resolv.conf";
|
||||
|
||||
if (stat(src, &st) < 0) {
|
||||
if (errno == ENOENT) {
|
||||
fprintf(stdout, "no dns configured\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
perror("stat resolve.conf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
hyper_mkdir("./etc", 0755);
|
||||
|
||||
fd = open("./etc/resolv.conf", O_CREAT| O_WRONLY, 0644);
|
||||
if (fd < 0) {
|
||||
perror("create /etc/resolv.conf failed");
|
||||
return -1;
|
||||
}
|
||||
close(fd);
|
||||
|
||||
if (mount(src, "./etc/resolv.conf", NULL, MS_BIND, NULL) < 0) {
|
||||
perror("bind to /etc/resolv.conf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -177,19 +439,14 @@ static int container_setup_mount(struct hyper_container *container)
|
||||
|
||||
static int container_setup_workdir(struct hyper_container *container)
|
||||
{
|
||||
if (container->workdir && chdir(container->workdir) < 0) {
|
||||
perror("change work directory failed");
|
||||
return -1;
|
||||
if (container->initialize) {
|
||||
// create workdir
|
||||
return hyper_mkdir(container->exec.workdir, 0755);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int container_setup_tty(int fd, struct hyper_container *container)
|
||||
{
|
||||
return hyper_dup_exec_tty(fd, &container->exec);
|
||||
}
|
||||
|
||||
static int hyper_rescan_scsi(void)
|
||||
{
|
||||
struct dirent **list;
|
||||
@@ -237,18 +494,21 @@ static int hyper_rescan_scsi(void)
|
||||
|
||||
struct hyper_container_arg {
|
||||
struct hyper_container *c;
|
||||
struct hyper_pod *pod;
|
||||
int pipe[2];
|
||||
int pipens[2];
|
||||
};
|
||||
|
||||
static int hyper_container_init(void *data)
|
||||
static int hyper_setup_container_rootfs(void *data)
|
||||
{
|
||||
struct hyper_container_arg *arg = data;
|
||||
struct hyper_container *container = arg->c;
|
||||
char root[512], oldroot[512];
|
||||
char root[512], rootfs[512];
|
||||
int setup_dns;
|
||||
uint32_t type;
|
||||
|
||||
fprintf(stdout, "%s in\n", __func__);
|
||||
if (container->exec.argv == NULL) {
|
||||
fprintf(stdout, "no cmd!\n");
|
||||
if (hyper_enter_sandbox(arg->pod, -1) < 0) {
|
||||
perror("enter sandbox failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -257,11 +517,6 @@ static int hyper_container_init(void *data)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (container_setup_env(container) < 0) {
|
||||
fprintf(stdout, "setup env failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mount("", "/", NULL, MS_SLAVE|MS_REC, NULL) < 0) {
|
||||
perror("mount SLAVE failed");
|
||||
goto fail;
|
||||
@@ -273,7 +528,7 @@ static int hyper_container_init(void *data)
|
||||
}
|
||||
|
||||
sprintf(root, "/tmp/hyper/%s/root/", container->id);
|
||||
if (hyper_mkdir(root) < 0) {
|
||||
if (hyper_mkdir(root, 0755) < 0) {
|
||||
perror("make root directroy failed");
|
||||
goto fail;
|
||||
}
|
||||
@@ -282,11 +537,21 @@ static int hyper_container_init(void *data)
|
||||
|
||||
if (container->fstype) {
|
||||
char dev[128];
|
||||
char *options = NULL;
|
||||
|
||||
if (container->scsiaddr) {
|
||||
free(container->image);
|
||||
container->image = NULL;
|
||||
hyper_find_sd(container->scsiaddr, &container->image);
|
||||
}
|
||||
|
||||
sprintf(dev, "/dev/%s", container->image);
|
||||
fprintf(stdout, "device %s\n", dev);
|
||||
|
||||
if (mount(dev, root, container->fstype, 0, NULL) < 0) {
|
||||
if (!strncmp(container->fstype, "xfs", strlen("xfs")))
|
||||
options = "nouuid";
|
||||
|
||||
if (mount(dev, root, container->fstype, 0, options) < 0) {
|
||||
perror("mount device failed");
|
||||
goto fail;
|
||||
}
|
||||
@@ -305,32 +570,54 @@ static int hyper_container_init(void *data)
|
||||
fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
|
||||
root, container->rootfs, container->exec.argv[0]);
|
||||
|
||||
hyper_list_dir(root);
|
||||
sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs);
|
||||
if (hyper_mkdir(oldroot) < 0) {
|
||||
perror("make oldroot directroy failed");
|
||||
sprintf(rootfs, "%s/%s/", root, container->rootfs);
|
||||
if (mount(rootfs, rootfs, NULL, MS_BIND|MS_REC, NULL) < 0) {
|
||||
perror("failed to bind rootfs");
|
||||
goto fail;
|
||||
}
|
||||
chdir(rootfs);
|
||||
|
||||
/*
|
||||
* Recreate dns resolver iif configured by pod spec. Other cases
|
||||
* are handled by hyperd instead.
|
||||
*/
|
||||
setup_dns = arg->pod->dns != NULL && arg->pod->d_num > 0;
|
||||
if (container_setup_init_layer(container, setup_dns) < 0) {
|
||||
fprintf(stderr, "container sets up init layer failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (mount("/", oldroot, NULL, MS_BIND|MS_REC, NULL) < 0) {
|
||||
perror("bind oldroot failed");
|
||||
if (container_setup_mount(container) < 0) {
|
||||
fprintf(stderr, "container sets up mount failed\n");
|
||||
goto fail;
|
||||
}
|
||||
/* reuse oldroot array */
|
||||
sprintf(oldroot, "%s/%s/", root, container->rootfs);
|
||||
/* pivot_root won't work, see
|
||||
* Documention/filesystem/ramfs-rootfs-initramfs.txt */
|
||||
chroot(oldroot);
|
||||
|
||||
chdir("/");
|
||||
// ignore error of setup modules
|
||||
container_setup_modules(container);
|
||||
|
||||
if (container_setup_volume(container) < 0) {
|
||||
fprintf(stderr, "container sets up voulme failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (container_setup_mount(container) < 0) {
|
||||
fprintf(stderr, "container sets up mount ns failed\n");
|
||||
if (container_setup_dns(container) < 0) {
|
||||
fprintf(stderr, "container sets up dns failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
// manipulate the rootfs of the container/namespace: move the prepared path @rootfs to /
|
||||
if (mount(rootfs, "/", NULL, MS_MOVE, NULL) < 0) {
|
||||
perror("failed to move rootfs");
|
||||
goto fail;
|
||||
}
|
||||
/* pivot_root won't work, see
|
||||
* Documention/filesystem/ramfs-rootfs-initramfs.txt */
|
||||
chroot(".");
|
||||
|
||||
chdir("/");
|
||||
|
||||
if (container_setup_sysctl(container) < 0) {
|
||||
fprintf(stderr, "container sets up sysctl failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -339,190 +626,149 @@ static int hyper_container_init(void *data)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
container_unmount_oldroot("/.oldroot");
|
||||
|
||||
fflush(stdout);
|
||||
|
||||
if (container_setup_tty(arg->pipe[1], container) < 0) {
|
||||
fprintf(stdout, "setup tty failed\n");
|
||||
/* wait for ns-opened ready message */
|
||||
if (hyper_get_type(arg->pipens[0], &type) < 0 || type != READY) {
|
||||
fprintf(stderr, "wait for /proc/self/ns/mnt opened failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(arg->pipe[0]);
|
||||
close(arg->pipe[1]);
|
||||
|
||||
execvp(container->exec.argv[0], container->exec.argv);
|
||||
|
||||
_exit(-1);
|
||||
hyper_send_type(arg->pipe[1], READY);
|
||||
fflush(NULL);
|
||||
_exit(0);
|
||||
|
||||
fail:
|
||||
container->exec.code = -1;
|
||||
hyper_send_type_block(arg->pipe[1], ERROR, 0);
|
||||
_exit(-1);
|
||||
hyper_send_type(arg->pipe[1], ERROR);
|
||||
_exit(125);
|
||||
}
|
||||
|
||||
int hyper_start_container(struct hyper_container *container)
|
||||
static int hyper_setup_pty(struct hyper_container *c)
|
||||
{
|
||||
int stacksize = getpagesize() * 4;
|
||||
void *stack = malloc(stacksize);
|
||||
char root[512];
|
||||
|
||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||
|
||||
if (hyper_mkdir(root, 0755) < 0) {
|
||||
perror("make container pts directroy failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("devpts", root, "devpts", MS_NOSUID,
|
||||
"newinstance,ptmxmode=0666,mode=0620") < 0) {
|
||||
perror("mount devpts failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod)
|
||||
{
|
||||
int stacksize = getpagesize() * 42;
|
||||
struct hyper_container_arg arg = {
|
||||
.c = container,
|
||||
.c = container,
|
||||
.pod = pod,
|
||||
.pipe = {-1, -1},
|
||||
.pipens = {-1, -1},
|
||||
};
|
||||
int flags = CLONE_NEWNS | SIGCHLD;
|
||||
char path[128];
|
||||
void *stack;
|
||||
uint32_t type;
|
||||
int pid;
|
||||
|
||||
if (container->image == NULL || container->exec.argv == NULL) {
|
||||
fprintf(stdout, "container root image %s, argv %p\n",
|
||||
container->image, container->exec.argv);
|
||||
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");
|
||||
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);
|
||||
if (pid < 0) {
|
||||
perror("create child process failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
container->exec.pid = pid;
|
||||
sprintf(path, "/proc/%d/ns/mnt", pid);
|
||||
container->ns = open(path, O_RDONLY | O_CLOEXEC);
|
||||
if (container->ns < 0) {
|
||||
perror("open container mount ns failed");
|
||||
goto fail;
|
||||
}
|
||||
hyper_send_type(arg.pipens[1], READY);
|
||||
|
||||
/* wait for ready message */
|
||||
if (hyper_get_type_block(arg.pipe[0], &type) < 0 || type != READY) {
|
||||
fprintf(stdout, "wait for container started failed\n");
|
||||
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
|
||||
fprintf(stderr, "wait for setup container rootfs failed\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
close(arg.pipe[0]);
|
||||
close(arg.pipe[1]);
|
||||
|
||||
fprintf(stdout, "container %s init pid is %d\n", container->id, pid);
|
||||
close(arg.pipens[0]);
|
||||
close(arg.pipens[1]);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
|
||||
container->exec.code = -1;
|
||||
close(container->ns);
|
||||
container->ns = -1;
|
||||
close(arg.pipe[0]);
|
||||
close(arg.pipe[1]);
|
||||
close(arg.pipens[0]);
|
||||
close(arg.pipens[1]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
int hyper_start_containers(struct hyper_pod *pod)
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* mount new proc directory */
|
||||
if (umount("/proc") < 0) {
|
||||
perror("umount proc filesystem failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (mount("proc", "/proc", "proc", 0, NULL) < 0) {
|
||||
perror("mount proc filesystem failed\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sethostname(pod->hostname, strlen(pod->hostname)) < 0) {
|
||||
perror("set host name failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < pod->c_num; i++)
|
||||
hyper_start_container(&pod->c[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_restart_containers(struct hyper_pod *pod)
|
||||
{
|
||||
int i;
|
||||
struct hyper_container *c;
|
||||
|
||||
for (i = 0; i < pod->c_num; i++) {
|
||||
c = &pod->c[i];
|
||||
|
||||
if (hyper_start_container(c) < 0) {
|
||||
fprintf(stderr, "restart container %s failed\n", c->id);
|
||||
hyper_send_type(pod->ctl.fd, ERROR);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (hyper_send_type(pod->ctl.fd, ACK) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id)
|
||||
{
|
||||
int i;
|
||||
struct hyper_container *container;
|
||||
|
||||
for (i = 0; i < pod->c_num; i++) {
|
||||
container = &pod->c[i];
|
||||
|
||||
if (strlen(container->id) != strlen(id))
|
||||
list_for_each_entry(c, &pod->containers, list) {
|
||||
if (strlen(c->id) != strlen(id))
|
||||
continue;
|
||||
|
||||
if (strncmp(container->id, id, strlen(id)))
|
||||
if (strncmp(c->id, id, strlen(id)))
|
||||
continue;
|
||||
|
||||
return container;
|
||||
return c;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void hyper_cleanup_container(struct hyper_pod *pod)
|
||||
void hyper_cleanup_container(struct hyper_container *c, struct hyper_pod *pod)
|
||||
{
|
||||
int i, j;
|
||||
struct hyper_container *c;
|
||||
struct volume *vol;
|
||||
struct env *env;
|
||||
struct fsmap *map;
|
||||
char root[512];
|
||||
|
||||
for (i = 0; i < pod->c_num; i++) {
|
||||
c = &pod->c[i];
|
||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
||||
perror("umount devpts failed");
|
||||
|
||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
||||
perror("umount devpts failed");
|
||||
close(c->ns);
|
||||
hyper_cleanup_container_portmapping(c, pod);
|
||||
hyper_free_container(c);
|
||||
}
|
||||
|
||||
free(c->id);
|
||||
free(c->rootfs);
|
||||
free(c->image);
|
||||
free(c->workdir);
|
||||
free(c->fstype);
|
||||
void hyper_cleanup_containers(struct hyper_pod *pod)
|
||||
{
|
||||
struct hyper_container *c, *n;
|
||||
|
||||
for (j = 0; j < c->vols_num; j++) {
|
||||
vol = &(c->vols[j]);
|
||||
free(vol->device);
|
||||
free(vol->mountpoint);
|
||||
free(vol->fstype);
|
||||
}
|
||||
free(c->vols);
|
||||
list_for_each_entry_safe(c, n, &pod->containers, list)
|
||||
hyper_cleanup_container(c, pod);
|
||||
|
||||
for (j = 0; j < c->envs_num; j++) {
|
||||
env = &(c->envs[j]);
|
||||
free(env->env);
|
||||
free(env->value);
|
||||
}
|
||||
free(c->envs);
|
||||
|
||||
for (j = 0; j < c->maps_num; j++) {
|
||||
map = &(c->maps[j]);
|
||||
free(map->source);
|
||||
free(map->path);
|
||||
}
|
||||
free(c->maps);
|
||||
}
|
||||
|
||||
free(pod->c);
|
||||
pod->c = NULL;
|
||||
pod->c_num = 0;
|
||||
pod->remains = 0;
|
||||
}
|
||||
|
||||
+31
-14
@@ -3,45 +3,62 @@
|
||||
|
||||
#include "exec.h"
|
||||
|
||||
struct env {
|
||||
char *env;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct volume {
|
||||
char *device;
|
||||
char *scsiaddr;
|
||||
char *mountpoint;
|
||||
char *fstype;
|
||||
int readonly;
|
||||
int docker;
|
||||
};
|
||||
|
||||
struct fsmap {
|
||||
char *source;
|
||||
char *path;
|
||||
int readonly;
|
||||
int docker;
|
||||
};
|
||||
|
||||
struct sysctl {
|
||||
char *path;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct port {
|
||||
int host_port;
|
||||
int container_port;
|
||||
char *protocol;
|
||||
};
|
||||
|
||||
struct hyper_container {
|
||||
struct list_head list;
|
||||
struct hyper_exec exec;
|
||||
int ns;
|
||||
uint32_t code;
|
||||
|
||||
// configs
|
||||
char *id;
|
||||
char *rootfs;
|
||||
char *image;
|
||||
char *workdir;
|
||||
char *scsiaddr;
|
||||
char *fstype;
|
||||
struct volume *vols;
|
||||
struct env *envs;
|
||||
struct fsmap *maps;
|
||||
struct sysctl *sys;
|
||||
struct port *ports;
|
||||
int vols_num;
|
||||
int envs_num;
|
||||
int maps_num;
|
||||
uint32_t code;
|
||||
struct hyper_exec exec;
|
||||
int sys_num;
|
||||
int ports_num;
|
||||
int initialize;
|
||||
};
|
||||
|
||||
struct hyper_pod;
|
||||
|
||||
int hyper_start_containers(struct hyper_pod *pod);
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
||||
int hyper_restart_containers(struct hyper_pod *pod);
|
||||
void hyper_cleanup_container(struct hyper_pod *pod);
|
||||
int hyper_setup_container(struct hyper_container *container, struct hyper_pod *pod);
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, const char *id);
|
||||
void hyper_cleanup_container(struct hyper_container *container, struct hyper_pod *pod);
|
||||
void hyper_cleanup_containers(struct hyper_pod *pod);
|
||||
void hyper_free_container(struct hyper_container *c);
|
||||
|
||||
#endif
|
||||
|
||||
+232
-40
@@ -5,33 +5,45 @@
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "util.h"
|
||||
#include "hyper.h"
|
||||
#include "event.h"
|
||||
|
||||
void hyper_reset_event(struct hyper_event *de)
|
||||
void hyper_reset_event(struct hyper_event *he)
|
||||
{
|
||||
free(de->buf.data);
|
||||
de->buf.data = NULL;
|
||||
memset(de, 0, sizeof(*de));
|
||||
free(he->rbuf.data);
|
||||
free(he->wbuf.data);
|
||||
close(he->fd);
|
||||
memset(he, 0, sizeof(*he));
|
||||
he->fd = -1;
|
||||
}
|
||||
|
||||
int hyper_init_event(struct hyper_event *de,
|
||||
struct hyper_event_ops *ops,
|
||||
uint32_t size, int to, void *arg)
|
||||
int hyper_init_event(struct hyper_event *he, struct hyper_event_ops *ops, void *arg)
|
||||
{
|
||||
struct hyper_buf *buf = &de->buf;
|
||||
struct hyper_buf *rbuf = &he->rbuf;
|
||||
struct hyper_buf *wbuf = &he->wbuf;
|
||||
|
||||
memset(buf, 0, sizeof(*buf));
|
||||
memset(rbuf, 0, sizeof(*rbuf));
|
||||
memset(wbuf, 0, sizeof(*wbuf));
|
||||
|
||||
de->ops = ops;
|
||||
de->ptr = arg;
|
||||
de->to = to;
|
||||
buf->size = size;
|
||||
he->ops = ops;
|
||||
he->ptr = arg;
|
||||
rbuf->size = ops->rbuf_size;
|
||||
wbuf->size = ops->wbuf_size;
|
||||
|
||||
if (size) {
|
||||
buf->data = malloc(size);
|
||||
if (buf->data == NULL) {
|
||||
fprintf(stderr, "allocate data for event failed\n");
|
||||
if (rbuf->size) {
|
||||
rbuf->data = malloc(rbuf->size);
|
||||
if (rbuf->data == NULL) {
|
||||
fprintf(stderr, "allocate read buffer for event failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (wbuf->size) {
|
||||
wbuf->data = malloc(wbuf->size);
|
||||
if (wbuf->data == NULL) {
|
||||
fprintf(stderr, "allocate write buffer for event failed\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@@ -39,21 +51,22 @@ int hyper_init_event(struct hyper_event *de,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_add_event(int efd, struct hyper_event *de)
|
||||
int hyper_add_event(int efd, struct hyper_event *he, int flag)
|
||||
{
|
||||
struct epoll_event event = {
|
||||
.events = EPOLLIN,
|
||||
.data.ptr = de,
|
||||
.events = flag,
|
||||
.data.ptr = he,
|
||||
};
|
||||
|
||||
if (hyper_setfd_nonblock(de->fd) < 0) {
|
||||
he->flag = flag;
|
||||
if (hyper_setfd_nonblock(he->fd) < 0) {
|
||||
perror("set fd nonblock failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s add event fd %d, %p\n", __func__, de->fd, de->ops);
|
||||
fprintf(stdout, "%s add event fd %d, %p\n", __func__, he->fd, he->ops);
|
||||
|
||||
if (epoll_ctl(efd, EPOLL_CTL_ADD, de->fd, &event) < 0) {
|
||||
if (epoll_ctl(efd, EPOLL_CTL_ADD, he->fd, &event) < 0) {
|
||||
perror("epoll_ctl fd failed");
|
||||
return -1;
|
||||
}
|
||||
@@ -61,31 +74,210 @@ int hyper_add_event(int efd, struct hyper_event *de)
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hyper_event_hup(struct hyper_event *de, int efd)
|
||||
int hyper_modify_event(int efd, struct hyper_event *he, int flag)
|
||||
{
|
||||
if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0)
|
||||
struct epoll_event event = {
|
||||
.events = flag,
|
||||
.data.ptr = he,
|
||||
};
|
||||
|
||||
if (he->flag == flag)
|
||||
return 0;
|
||||
|
||||
he->flag = flag;
|
||||
fprintf(stdout, "%s modify event fd %d, %p, event %d\n",
|
||||
__func__, he->fd, he, flag);
|
||||
|
||||
if (epoll_ctl(efd, EPOLL_CTL_MOD, he->fd, &event) < 0) {
|
||||
perror("epoll_ctl fd failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_requeue_event(int efd, struct hyper_event *ev)
|
||||
{
|
||||
struct epoll_event event = {
|
||||
.events = ev->flag,
|
||||
.data.ptr = ev,
|
||||
};
|
||||
|
||||
if (epoll_ctl(efd, EPOLL_CTL_DEL, ev->fd, NULL) < 0) {
|
||||
perror("epoll_ctl del fd failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (epoll_ctl(efd, EPOLL_CTL_ADD, ev->fd, &event) < 0) {
|
||||
perror("epoll_ctl add fd failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hyper_getmsg_len(struct hyper_event *he, uint32_t *len)
|
||||
{
|
||||
struct hyper_buf *buf = &he->rbuf;
|
||||
|
||||
if (buf->get < he->ops->len_offset + 4)
|
||||
return -1;
|
||||
|
||||
*len = hyper_get_be32(buf->data + he->ops->len_offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_event_read(struct hyper_event *he, int efd)
|
||||
{
|
||||
struct hyper_buf *buf = &he->rbuf;
|
||||
uint32_t len = 4;
|
||||
uint8_t data[4];
|
||||
int offset = he->ops->len_offset;
|
||||
int end = offset + 4;
|
||||
int size;
|
||||
|
||||
fprintf(stdout, "%s\n", __func__);
|
||||
|
||||
while (hyper_getmsg_len(he, &len) < 0) {
|
||||
size = read(he->fd, buf->data + buf->get, end - buf->get);
|
||||
if (size > 0) {
|
||||
buf->get += size;
|
||||
fprintf(stdout, "already read %" PRIu32 " bytes data\n",
|
||||
buf->get);
|
||||
|
||||
if (he->ops->ack) {
|
||||
/* control channel, need ack */
|
||||
hyper_set_be32(data, size);
|
||||
hyper_send_msg(he->fd, NEXT, 4, data);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
|
||||
if (errno != EAGAIN && size != 0) {
|
||||
perror("fail to read");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stdout, "get length %" PRIu32"\n", len);
|
||||
if (len > buf->size) {
|
||||
fprintf(stderr, "get length %" PRIu32", too long\n", len);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (buf->get < len) {
|
||||
size = read(he->fd, buf->data + buf->get, len - buf->get);
|
||||
if (size > 0) {
|
||||
buf->get += size;
|
||||
fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n",
|
||||
size, buf->get);
|
||||
if (he->ops->ack) {
|
||||
/* control channel, need ack */
|
||||
hyper_set_be32(data, size);
|
||||
hyper_send_msg(he->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 (he->ops->handle(he, 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;
|
||||
}
|
||||
|
||||
int hyper_event_write(struct hyper_event *he, int efd)
|
||||
{
|
||||
struct hyper_buf *buf = &he->wbuf;
|
||||
uint32_t len = 0;
|
||||
int size = 0;
|
||||
|
||||
while (len < buf->get) {
|
||||
size = write(he->fd, buf->data + len, buf->get - len);
|
||||
if (size <= 0) {
|
||||
if (errno == EINTR)
|
||||
continue;
|
||||
if (errno == EAGAIN || size == 0)
|
||||
break;
|
||||
return -1;
|
||||
}
|
||||
len += size;
|
||||
}
|
||||
|
||||
buf->get -= len;
|
||||
memmove(buf->data, buf->data + len, buf->get);
|
||||
|
||||
if (buf->get == 0) {
|
||||
hyper_modify_event(ctl.efd, he, he->flag & ~(EPOLLOUT| EPOLLPRI));
|
||||
} else if (!FULL(buf)) {
|
||||
hyper_modify_event(ctl.efd, he, he->flag & ~EPOLLPRI);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hyper_event_hup(struct hyper_event *he, int efd)
|
||||
{
|
||||
if (epoll_ctl(efd, EPOLL_CTL_DEL, he->fd, NULL) < 0)
|
||||
perror("epoll_ctl del epoll event failed");
|
||||
close(de->fd);
|
||||
hyper_reset_event(de);
|
||||
hyper_reset_event(he);
|
||||
}
|
||||
|
||||
int hyper_handle_event(int efd, struct epoll_event *event)
|
||||
{
|
||||
struct hyper_event *de = event->data.ptr;
|
||||
struct hyper_event *he = event->data.ptr;
|
||||
fprintf(stdout, "%s get event %d, he %p, fd %d. ops %p\n",
|
||||
__func__, event->events, he, he->fd, he->ops);
|
||||
|
||||
if (event->events & EPOLLHUP) {
|
||||
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
|
||||
__func__, de, de->fd, de->ops);
|
||||
if (de->ops->hup)
|
||||
de->ops->hup(de, efd);
|
||||
/* do not handle hup event if have in event */
|
||||
if ((event->events & EPOLLIN) && he->ops->read) {
|
||||
fprintf(stdout, "%s event EPOLLIN, he %p, fd %d, %p\n",
|
||||
__func__, he, he->fd, he->ops);
|
||||
if (he->ops->read && he->ops->read(he, efd) < 0)
|
||||
return -1;
|
||||
} else if (event->events & EPOLLHUP) {
|
||||
fprintf(stdout, "%s event EPOLLHUP, he %p, fd %d, %p\n",
|
||||
__func__, he, he->fd, he->ops);
|
||||
if (he->ops->hup)
|
||||
he->ops->hup(he, efd);
|
||||
return 0;
|
||||
} else if (event->events & EPOLLIN) {
|
||||
return de->ops->read(de);
|
||||
} else if (event->events & EPOLLERR) {
|
||||
fprintf(stderr, "get epoll err of not epool in event\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s get unknown event %d\n", __func__, event->events);
|
||||
return -1;
|
||||
if (event->events & EPOLLOUT) {
|
||||
fprintf(stdout, "%s event EPOLLOUT, he %p, fd %d, %p\n",
|
||||
__func__, he, he->fd, he->ops);
|
||||
if (he->ops->write && he->ops->write(he, efd) < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (event->events & EPOLLERR) {
|
||||
fprintf(stderr, "get epoll err of not epool in event\n");
|
||||
if (he->ops->hup)
|
||||
he->ops->hup(he, efd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
+18
-6
@@ -7,10 +7,14 @@
|
||||
struct hyper_event;
|
||||
|
||||
struct hyper_event_ops {
|
||||
int (*read)(struct hyper_event *e);
|
||||
int (*getlen)(struct hyper_event *e, uint32_t *len);
|
||||
int (*read)(struct hyper_event *e, int efd);
|
||||
int (*write)(struct hyper_event *e, int efd);
|
||||
int (*handle)(struct hyper_event *e, uint32_t len);
|
||||
void (*hup)(struct hyper_event *e, int efd);
|
||||
int rbuf_size;
|
||||
int wbuf_size;
|
||||
int len_offset;
|
||||
int ack;
|
||||
};
|
||||
|
||||
struct hyper_buf {
|
||||
@@ -21,16 +25,24 @@ struct hyper_buf {
|
||||
|
||||
struct hyper_event {
|
||||
int fd;
|
||||
int to;
|
||||
struct hyper_buf buf;
|
||||
int flag;
|
||||
struct hyper_buf rbuf;
|
||||
struct hyper_buf wbuf;
|
||||
struct hyper_event_ops *ops;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
int hyper_add_event(int efd, struct hyper_event *de);
|
||||
#define FULL(buf) \
|
||||
(buf->size - buf->get <= 12)
|
||||
|
||||
int hyper_add_event(int efd, struct hyper_event *de, int flag);
|
||||
int hyper_modify_event(int efd, struct hyper_event *de, int flag);
|
||||
int hyper_requeue_event(int efd, struct hyper_event *ev);
|
||||
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops,
|
||||
uint32_t size, int to, void *arg);
|
||||
void *arg);
|
||||
int hyper_handle_event(int efd, struct epoll_event *event);
|
||||
void hyper_reset_event(struct hyper_event *de);
|
||||
void hyper_event_hup(struct hyper_event *de, int efd);
|
||||
int hyper_event_read(struct hyper_event *dei, int efd);
|
||||
int hyper_event_write(struct hyper_event *de, int efd);
|
||||
#endif
|
||||
|
||||
+655
-336
File diff suppressed because it is too large
Load Diff
+32
-14
@@ -4,33 +4,51 @@
|
||||
#include "list.h"
|
||||
#include "event.h"
|
||||
|
||||
struct env {
|
||||
char *env;
|
||||
char *value;
|
||||
};
|
||||
|
||||
struct hyper_exec {
|
||||
struct list_head list;
|
||||
struct hyper_event e;
|
||||
char *id;
|
||||
char *pty;
|
||||
char **argv;
|
||||
int argc;
|
||||
uint64_t seq;
|
||||
struct hyper_event stdinev;
|
||||
struct hyper_event stdoutev;
|
||||
struct hyper_event stderrev;
|
||||
int pid;
|
||||
int ptyno;
|
||||
int init;
|
||||
int ptyfd;
|
||||
int stdinfd;
|
||||
int stdoutfd;
|
||||
int stderrfd;
|
||||
uint8_t close_stdin_request;
|
||||
uint8_t code;
|
||||
uint8_t exit;
|
||||
uint8_t ref;
|
||||
|
||||
// configs
|
||||
char *id;
|
||||
char *user;
|
||||
char *group;
|
||||
char **additional_groups;
|
||||
int nr_additional_groups;
|
||||
struct env *envs;
|
||||
int envs_num;
|
||||
char **argv;
|
||||
int argc;
|
||||
int tty; // use tty or not
|
||||
uint64_t seq;
|
||||
uint64_t errseq;
|
||||
char *workdir;
|
||||
};
|
||||
|
||||
struct hyper_pod;
|
||||
|
||||
int hyper_exec_cmd(char *json, int length);
|
||||
int hyper_release_exec(struct hyper_exec *, struct hyper_pod *);
|
||||
int hyper_container_execcmd(struct hyper_pod *pod);
|
||||
int hyper_setup_exec_tty(struct hyper_exec *e);
|
||||
int hyper_dup_exec_tty(int fd, struct hyper_exec *e);
|
||||
int hyper_run_process(struct hyper_exec *e);
|
||||
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
|
||||
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
|
||||
int hyper_send_exec_eof(int to, struct hyper_pod *pod,
|
||||
struct list_head *head, int pid,
|
||||
uint8_t code);
|
||||
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code);
|
||||
void hyper_cleanup_exec(struct hyper_pod *pod);
|
||||
|
||||
extern struct hyper_event_ops pts_ops;
|
||||
#endif
|
||||
|
||||
+72
-25
@@ -1,29 +1,43 @@
|
||||
#ifndef _DVM_H_
|
||||
#define _DVM_H_
|
||||
#ifndef _HYPER_H_
|
||||
#define _HYPER_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "list.h"
|
||||
#include "exec.h"
|
||||
#include "event.h"
|
||||
#include "container.h"
|
||||
#include "portmapping.h"
|
||||
|
||||
enum {
|
||||
SETDVM,
|
||||
RESERVED,
|
||||
STARTPOD,
|
||||
GETPOD,
|
||||
STOPPOD,
|
||||
DESTROYPOD,
|
||||
RESTARTCONTAINER,
|
||||
EXECCMD,
|
||||
FINISHCMD,
|
||||
CMDFINISHED,
|
||||
READY,
|
||||
ACK,
|
||||
ERROR,
|
||||
WINSIZE,
|
||||
PING,
|
||||
FINISH,
|
||||
PODFINISHED,
|
||||
NEXT,
|
||||
WRITEFILE,
|
||||
READFILE,
|
||||
NEWCONTAINER,
|
||||
KILLCONTAINER,
|
||||
ONLINECPUMEM,
|
||||
SETUPINTERFACE,
|
||||
SETUPROUTE,
|
||||
REMOVECONTAINER,
|
||||
};
|
||||
|
||||
enum {
|
||||
@@ -33,48 +47,81 @@ enum {
|
||||
};
|
||||
|
||||
struct hyper_pod {
|
||||
struct hyper_container *c;
|
||||
struct hyper_interface *iface;
|
||||
struct hyper_route *rt;
|
||||
struct list_head pe_head;
|
||||
struct list_head ce_head;
|
||||
struct portmapping_white_list *portmap_white_lists;
|
||||
char **dns;
|
||||
struct list_head containers;
|
||||
struct list_head exec_head;
|
||||
char *hostname;
|
||||
char *tag;
|
||||
char *channel;
|
||||
char *share_tag;
|
||||
int init_pid;
|
||||
uint32_t c_num;
|
||||
uint32_t i_num;
|
||||
uint32_t r_num;
|
||||
uint32_t e_num;
|
||||
uint32_t d_num;
|
||||
uint32_t type;
|
||||
uint32_t code;
|
||||
/* how many containers are running */
|
||||
uint32_t remains;
|
||||
uint8_t policy;
|
||||
int efd;
|
||||
struct hyper_event sig;
|
||||
struct hyper_event ctl;
|
||||
};
|
||||
|
||||
struct portmapping_white_list {
|
||||
char **internal_networks;
|
||||
char **external_networks;
|
||||
uint32_t i_num;
|
||||
uint32_t e_num;
|
||||
};
|
||||
|
||||
struct hyper_win_size {
|
||||
char *tty;
|
||||
int row;
|
||||
int column;
|
||||
uint64_t seq;
|
||||
};
|
||||
|
||||
struct hyper_ctl {
|
||||
int efd;
|
||||
struct hyper_event sig;
|
||||
struct hyper_event tty;
|
||||
struct hyper_event chan;
|
||||
struct hyper_event ctl;
|
||||
struct hyper_reader {
|
||||
char *id;
|
||||
char *file;
|
||||
};
|
||||
|
||||
int hyper_mkdir(char *hyper_path);
|
||||
struct hyper_writter {
|
||||
char *id;
|
||||
char *file;
|
||||
uint8_t *data;
|
||||
int len;
|
||||
};
|
||||
|
||||
struct hyper_ctl {
|
||||
int efd;
|
||||
struct hyper_event tty;
|
||||
struct hyper_event chan;
|
||||
};
|
||||
|
||||
static inline int hyper_symlink(char *oldpath, char *newpath)
|
||||
{
|
||||
return symlink(oldpath, newpath);
|
||||
}
|
||||
|
||||
static inline int hyper_unlink(char *hyper_path)
|
||||
{
|
||||
return unlink(hyper_path);
|
||||
}
|
||||
|
||||
static inline int hyper_create(char *hyper_path)
|
||||
{
|
||||
int fd = creat(hyper_path, 0755);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_open_serial(char *tty);
|
||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
||||
void hyper_cleanup_pod(struct hyper_pod *pod);
|
||||
int hyper_enter_sandbox(struct hyper_pod *pod, int pidpipe);
|
||||
|
||||
extern struct hyper_pod global_pod;
|
||||
extern struct hyper_ctl ctl;
|
||||
extern struct hyper_exec *global_exec;
|
||||
extern sigset_t orig_mask;
|
||||
#endif
|
||||
|
||||
+834
-533
File diff suppressed because it is too large
Load Diff
+11
-4
@@ -164,14 +164,18 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
int i;
|
||||
jsmntok_t *token;
|
||||
int count = 0;
|
||||
int num = 0;
|
||||
int out = 0;
|
||||
|
||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
||||
for (; parser->pos < len && js[parser->pos] != '\0' && !out; parser->pos++) {
|
||||
char c;
|
||||
jsmntype_t type;
|
||||
|
||||
c = js[parser->pos];
|
||||
switch (c) {
|
||||
case '{': case '[':
|
||||
case '{':
|
||||
num++;
|
||||
case '[':
|
||||
count++;
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
@@ -189,7 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
token->start = parser->pos;
|
||||
parser->toksuper = parser->toknext - 1;
|
||||
break;
|
||||
case '}': case ']':
|
||||
case '}':
|
||||
if (--num <= 0)
|
||||
out = 1;
|
||||
case ']':
|
||||
if (tokens == NULL)
|
||||
break;
|
||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||
@@ -221,7 +228,7 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
||||
|
||||
parser->toksuper = -1;
|
||||
token->end = parser->pos + 1;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Error if unmatched closing bracket */
|
||||
|
||||
@@ -7,8 +7,12 @@
|
||||
#include <unistd.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
|
||||
#include "hyper.h"
|
||||
#include "util.h"
|
||||
#include "parse.h"
|
||||
#include "../config.h"
|
||||
|
||||
void hyper_set_be32(uint8_t *buf, uint32_t val)
|
||||
{
|
||||
@@ -55,7 +59,9 @@ int hyper_send_data(int fd, uint8_t *data, uint32_t len)
|
||||
perror("send hyper data failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
#if WITH_VBOX
|
||||
tcdrain(fd);
|
||||
#endif
|
||||
length += size;
|
||||
}
|
||||
|
||||
@@ -86,7 +92,7 @@ int hyper_send_type(int fd, uint32_t type)
|
||||
return hyper_send_msg(fd, type, 0, NULL);
|
||||
}
|
||||
|
||||
int hyper_get_type_block(int fd, uint32_t *type)
|
||||
int hyper_get_type(int fd, uint32_t *type)
|
||||
{
|
||||
int len = 0, size;
|
||||
uint8_t buf[8];
|
||||
@@ -107,42 +113,20 @@ int hyper_get_type_block(int fd, uint32_t *type)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack)
|
||||
int hyper_send_msg_block(int fd, uint32_t type, uint32_t len, uint8_t *data)
|
||||
{
|
||||
int ret = 0, flags;
|
||||
uint32_t t;
|
||||
int ret, flags;
|
||||
|
||||
flags = fcntl(fd, F_GETFL, 0);
|
||||
flags = hyper_setfd_block(fd);
|
||||
if (flags < 0) {
|
||||
fprintf(stderr, "get fd flag failed\n");
|
||||
fprintf(stderr, "%s fail to set fd block\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) {
|
||||
perror("set fd BLOCK failed");
|
||||
return -1;
|
||||
}
|
||||
ret = hyper_send_msg(fd, type, len, data);
|
||||
|
||||
ret = hyper_send_msg(fd, type, 0, NULL);
|
||||
if (ret < 0)
|
||||
goto out;
|
||||
|
||||
if (need_ack == 0)
|
||||
goto out;
|
||||
|
||||
ret = hyper_get_type_block(fd, &t);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "can not get type\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
fprintf(stdout, "get type %" PRIu32"\n", type);
|
||||
|
||||
if (t != ACK)
|
||||
ret = -1;
|
||||
out:
|
||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
||||
perror("set fd BLOCK failed");
|
||||
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||
perror("restore fd flag failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -303,14 +287,17 @@ static int hyper_remove_nic(char *device)
|
||||
{
|
||||
char path[256], real[128];
|
||||
int fd;
|
||||
ssize_t size;
|
||||
|
||||
sprintf(path, "/sys/class/net/%s", device);
|
||||
|
||||
if (readlink(path, real, 128) < 0) {
|
||||
size = readlink(path, real, 128);
|
||||
if (size < 0 || size > 127) {
|
||||
perror("fail to read link directory");
|
||||
return -1;
|
||||
}
|
||||
|
||||
real[size] = '\0';
|
||||
sprintf(path, "/sys/%s/../../../remove", real + 5);
|
||||
|
||||
fprintf(stdout, "get net sys path %s\n", path);
|
||||
@@ -672,6 +659,11 @@ static int hyper_cleanup_interface(struct rtnl_handle *rth,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Don't down&remove lo device */
|
||||
if (strcmp(iface->device, "lo") == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hyper_down_nic(rth, iface->ifindex) < 0) {
|
||||
fprintf(stderr, "up device %d failed\n", iface->ifindex);
|
||||
return -1;
|
||||
@@ -791,3 +783,127 @@ void hyper_cleanup_network(struct hyper_pod *pod)
|
||||
pod->i_num = 0;
|
||||
netlink_close(&rth);
|
||||
}
|
||||
|
||||
int hyper_cmd_setup_interface(char *json, int length)
|
||||
{
|
||||
int ret = -1;
|
||||
struct hyper_interface *iface;
|
||||
struct rtnl_handle rth;
|
||||
|
||||
if (hyper_rescan() < 0)
|
||||
return -1;
|
||||
|
||||
if (netlink_open(&rth) < 0)
|
||||
return -1;
|
||||
|
||||
|
||||
iface = hyper_parse_setup_interface(json, length);
|
||||
if (iface == NULL) {
|
||||
fprintf(stderr, "parse interface failed\n");
|
||||
goto out;
|
||||
}
|
||||
ret = hyper_setup_interface(&rth, iface);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "link up device %s failed\n", iface->device);
|
||||
goto out1;
|
||||
}
|
||||
ret = 0;
|
||||
out1:
|
||||
free(iface->device);
|
||||
free(iface->ipaddr);
|
||||
free(iface->mask);
|
||||
free(iface);
|
||||
out:
|
||||
netlink_close(&rth);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_cmd_setup_route(char *json, int length) {
|
||||
struct hyper_route *rts = NULL;
|
||||
int i, ret = -1;
|
||||
uint32_t r_num;
|
||||
struct rtnl_handle rth;
|
||||
|
||||
if (netlink_open(&rth) < 0)
|
||||
return -1;
|
||||
|
||||
if (hyper_parse_setup_routes(&rts, &r_num, json, length) < 0) {
|
||||
fprintf(stderr, "parse route failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < r_num; i++) {
|
||||
ret = hyper_setup_route(&rth, &rts[i]);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "setup route failed\n");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
netlink_close(&rth);
|
||||
free(rts);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_setup_dns(struct hyper_pod *pod)
|
||||
{
|
||||
int i, fd, ret = -1;
|
||||
char buf[28];
|
||||
|
||||
if (pod->dns == NULL)
|
||||
return 0;
|
||||
|
||||
fd = open("/tmp/hyper/resolv.conf", O_CREAT| O_TRUNC| O_WRONLY, 0644);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("create /tmp/resolv.conf failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < pod->d_num; i++) {
|
||||
int size = snprintf(buf, sizeof(buf), "nameserver %s\n", pod->dns[i]);
|
||||
int len = 0, l;
|
||||
|
||||
if (size < 0) {
|
||||
fprintf(stderr, "sprintf resolv.conf entry failed\n");
|
||||
goto out;
|
||||
}
|
||||
|
||||
while (len < size) {
|
||||
l = write(fd, buf + len, size - len);
|
||||
if (l < 0) {
|
||||
perror("fail to write resolv.conf");
|
||||
goto out;
|
||||
}
|
||||
len += l;
|
||||
}
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
close(fd);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void hyper_cleanup_dns(struct hyper_pod *pod)
|
||||
{
|
||||
int fd, i;
|
||||
|
||||
for (i = 0; i < pod->d_num; i++) {
|
||||
free(pod->dns[i]);
|
||||
}
|
||||
|
||||
free(pod->dns);
|
||||
pod->dns = NULL;
|
||||
pod->d_num = 0;
|
||||
|
||||
fd = open("/tmp/hyper/resolv.conf", O_WRONLY| O_TRUNC);
|
||||
if (fd < 0) {
|
||||
perror("open /tmp/hyper/resolv.conf failed");
|
||||
return;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
}
|
||||
|
||||
@@ -47,11 +47,15 @@ uint32_t hyper_get_be32(uint8_t *buf);
|
||||
void hyper_set_be64(uint8_t *buf, uint64_t val);
|
||||
uint64_t hyper_get_be64(uint8_t *buf);
|
||||
int hyper_setup_network(struct hyper_pod *pod);
|
||||
int hyper_cmd_setup_interface(char *json, int length);
|
||||
int hyper_cmd_setup_route(char *json, int length);
|
||||
void hyper_cleanup_network(struct hyper_pod *pod);
|
||||
int hyper_get_type_block(int fd, uint32_t *type);
|
||||
int hyper_setup_dns(struct hyper_pod *pod);
|
||||
void hyper_cleanup_dns(struct hyper_pod *pod);
|
||||
int hyper_get_type(int fd, uint32_t *type);
|
||||
int hyper_send_type(int fd, uint32_t type);
|
||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack);
|
||||
int hyper_send_msg(int fd, uint32_t type, uint32_t len,
|
||||
uint8_t *message);
|
||||
int hyper_send_msg(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||
int hyper_send_msg_block(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||
int hyper_send_data(int fd, uint8_t *data, uint32_t len);
|
||||
#endif
|
||||
|
||||
+1140
-202
File diff suppressed because it is too large
Load Diff
+10
-2
@@ -1,13 +1,21 @@
|
||||
#ifndef _DVM_JSON_H_
|
||||
#define _DVM_JSON_H_
|
||||
#ifndef _PARSE_H_
|
||||
#define _PARSE_H_
|
||||
|
||||
#include "hyper.h"
|
||||
#include "jsmn.h"
|
||||
#include "parson.h"
|
||||
|
||||
int hyper_parse_pod(struct hyper_pod *pod, char *json, int length);
|
||||
struct hyper_exec *hyper_parse_execcmd(char *json, int length);
|
||||
char *json_token_str(char *js, jsmntok_t *t);
|
||||
int json_token_streq(char *js, jsmntok_t *t, char *s);
|
||||
int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length);
|
||||
int hyper_parse_write_file(struct hyper_writter *writter, char *json, int length);
|
||||
int hyper_parse_read_file(struct hyper_reader *reader, char *json, int length);
|
||||
struct hyper_container *hyper_parse_new_container(struct hyper_pod *pod, char *json, int length);
|
||||
void hyper_free_container(struct hyper_container *c);
|
||||
struct hyper_interface *hyper_parse_setup_interface(char *json, int length);
|
||||
int hyper_parse_setup_routes(struct hyper_route **routes, uint32_t *r_num, char *json, int length);
|
||||
JSON_Value *hyper_json_parse(char *json, int length);
|
||||
|
||||
#endif
|
||||
|
||||
+2070
File diff suppressed because it is too large
Load Diff
+223
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
Parson ( http://kgabis.github.com/parson/ )
|
||||
Copyright (c) 2012 - 2016 Krzysztof Gabis
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef parson_parson_h
|
||||
#define parson_parson_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
/* Types and enums */
|
||||
typedef struct json_object_t JSON_Object;
|
||||
typedef struct json_array_t JSON_Array;
|
||||
typedef struct json_value_t JSON_Value;
|
||||
|
||||
enum json_value_type {
|
||||
JSONError = -1,
|
||||
JSONNull = 1,
|
||||
JSONString = 2,
|
||||
JSONNumber = 3,
|
||||
JSONObject = 4,
|
||||
JSONArray = 5,
|
||||
JSONBoolean = 6
|
||||
};
|
||||
typedef int JSON_Value_Type;
|
||||
|
||||
enum json_result_t {
|
||||
JSONSuccess = 0,
|
||||
JSONFailure = -1
|
||||
};
|
||||
typedef int JSON_Status;
|
||||
|
||||
typedef void * (*JSON_Malloc_Function)(size_t);
|
||||
typedef void (*JSON_Free_Function)(void *);
|
||||
|
||||
/* Call only once, before calling any other function from parson API. If not called, malloc and free
|
||||
from stdlib will be used for all allocations */
|
||||
void json_set_allocation_functions(JSON_Malloc_Function malloc_fun, JSON_Free_Function free_fun);
|
||||
|
||||
/* Parses first JSON value in a file, returns NULL in case of error */
|
||||
JSON_Value * json_parse_file(const char *filename);
|
||||
|
||||
/* Parses first JSON value in a file and ignores comments (/ * * / and //),
|
||||
returns NULL in case of error */
|
||||
JSON_Value * json_parse_file_with_comments(const char *filename);
|
||||
|
||||
/* Parses first JSON value in a string, returns NULL in case of error */
|
||||
JSON_Value * json_parse_string(const char *string);
|
||||
|
||||
/* Parses first JSON value in a string and ignores comments (/ * * / and //),
|
||||
returns NULL in case of error */
|
||||
JSON_Value * json_parse_string_with_comments(const char *string);
|
||||
|
||||
/* Serialization */
|
||||
size_t json_serialization_size(const JSON_Value *value); /* returns 0 on fail */
|
||||
JSON_Status json_serialize_to_buffer(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
||||
JSON_Status json_serialize_to_file(const JSON_Value *value, const char *filename);
|
||||
char * json_serialize_to_string(const JSON_Value *value);
|
||||
|
||||
/* Pretty serialization */
|
||||
size_t json_serialization_size_pretty(const JSON_Value *value); /* returns 0 on fail */
|
||||
JSON_Status json_serialize_to_buffer_pretty(const JSON_Value *value, char *buf, size_t buf_size_in_bytes);
|
||||
JSON_Status json_serialize_to_file_pretty(const JSON_Value *value, const char *filename);
|
||||
char * json_serialize_to_string_pretty(const JSON_Value *value);
|
||||
|
||||
void json_free_serialized_string(char *string); /* frees string from json_serialize_to_string and json_serialize_to_string_pretty */
|
||||
|
||||
/* Comparing */
|
||||
int json_value_equals(const JSON_Value *a, const JSON_Value *b);
|
||||
|
||||
/* Validation
|
||||
This is *NOT* JSON Schema. It validates json by checking if object have identically
|
||||
named fields with matching types.
|
||||
For example schema {"name":"", "age":0} will validate
|
||||
{"name":"Joe", "age":25} and {"name":"Joe", "age":25, "gender":"m"},
|
||||
but not {"name":"Joe"} or {"name":"Joe", "age":"Cucumber"}.
|
||||
In case of arrays, only first value in schema is checked against all values in tested array.
|
||||
Empty objects ({}) validate all objects, empty arrays ([]) validate all arrays,
|
||||
null validates values of every type.
|
||||
*/
|
||||
JSON_Status json_validate(const JSON_Value *schema, const JSON_Value *value);
|
||||
|
||||
/*
|
||||
* JSON Object
|
||||
*/
|
||||
JSON_Value * json_object_get_value (const JSON_Object *object, const char *name);
|
||||
const char * json_object_get_string (const JSON_Object *object, const char *name);
|
||||
JSON_Object * json_object_get_object (const JSON_Object *object, const char *name);
|
||||
JSON_Array * json_object_get_array (const JSON_Object *object, const char *name);
|
||||
double json_object_get_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
|
||||
int json_object_get_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
||||
|
||||
/* dotget functions enable addressing values with dot notation in nested objects,
|
||||
just like in structs or c++/java/c# objects (e.g. objectA.objectB.value).
|
||||
Because valid names in JSON can contain dots, some values may be inaccessible
|
||||
this way. */
|
||||
JSON_Value * json_object_dotget_value (const JSON_Object *object, const char *name);
|
||||
const char * json_object_dotget_string (const JSON_Object *object, const char *name);
|
||||
JSON_Object * json_object_dotget_object (const JSON_Object *object, const char *name);
|
||||
JSON_Array * json_object_dotget_array (const JSON_Object *object, const char *name);
|
||||
double json_object_dotget_number (const JSON_Object *object, const char *name); /* returns 0 on fail */
|
||||
int json_object_dotget_boolean(const JSON_Object *object, const char *name); /* returns -1 on fail */
|
||||
|
||||
/* Functions to get available names */
|
||||
size_t json_object_get_count (const JSON_Object *object);
|
||||
const char * json_object_get_name (const JSON_Object *object, size_t index);
|
||||
JSON_Value * json_object_get_value_at(const JSON_Object *object, size_t index);
|
||||
|
||||
/* Creates new name-value pair or frees and replaces old value with a new one.
|
||||
* json_object_set_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_object_set_value(JSON_Object *object, const char *name, JSON_Value *value);
|
||||
JSON_Status json_object_set_string(JSON_Object *object, const char *name, const char *string);
|
||||
JSON_Status json_object_set_number(JSON_Object *object, const char *name, double number);
|
||||
JSON_Status json_object_set_boolean(JSON_Object *object, const char *name, int boolean);
|
||||
JSON_Status json_object_set_null(JSON_Object *object, const char *name);
|
||||
|
||||
/* Works like dotget functions, but creates whole hierarchy if necessary.
|
||||
* json_object_dotset_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_object_dotset_value(JSON_Object *object, const char *name, JSON_Value *value);
|
||||
JSON_Status json_object_dotset_string(JSON_Object *object, const char *name, const char *string);
|
||||
JSON_Status json_object_dotset_number(JSON_Object *object, const char *name, double number);
|
||||
JSON_Status json_object_dotset_boolean(JSON_Object *object, const char *name, int boolean);
|
||||
JSON_Status json_object_dotset_null(JSON_Object *object, const char *name);
|
||||
|
||||
/* Frees and removes name-value pair */
|
||||
JSON_Status json_object_remove(JSON_Object *object, const char *name);
|
||||
|
||||
/* Works like dotget function, but removes name-value pair only on exact match. */
|
||||
JSON_Status json_object_dotremove(JSON_Object *object, const char *key);
|
||||
|
||||
/* Removes all name-value pairs in object */
|
||||
JSON_Status json_object_clear(JSON_Object *object);
|
||||
|
||||
/*
|
||||
*JSON Array
|
||||
*/
|
||||
JSON_Value * json_array_get_value (const JSON_Array *array, size_t index);
|
||||
const char * json_array_get_string (const JSON_Array *array, size_t index);
|
||||
JSON_Object * json_array_get_object (const JSON_Array *array, size_t index);
|
||||
JSON_Array * json_array_get_array (const JSON_Array *array, size_t index);
|
||||
double json_array_get_number (const JSON_Array *array, size_t index); /* returns 0 on fail */
|
||||
int json_array_get_boolean(const JSON_Array *array, size_t index); /* returns -1 on fail */
|
||||
size_t json_array_get_count (const JSON_Array *array);
|
||||
|
||||
/* Frees and removes value at given index, does nothing and returns JSONFailure if index doesn't exist.
|
||||
* Order of values in array may change during execution. */
|
||||
JSON_Status json_array_remove(JSON_Array *array, size_t i);
|
||||
|
||||
/* Frees and removes from array value at given index and replaces it with given one.
|
||||
* Does nothing and returns JSONFailure if index doesn't exist.
|
||||
* json_array_replace_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_array_replace_value(JSON_Array *array, size_t i, JSON_Value *value);
|
||||
JSON_Status json_array_replace_string(JSON_Array *array, size_t i, const char* string);
|
||||
JSON_Status json_array_replace_number(JSON_Array *array, size_t i, double number);
|
||||
JSON_Status json_array_replace_boolean(JSON_Array *array, size_t i, int boolean);
|
||||
JSON_Status json_array_replace_null(JSON_Array *array, size_t i);
|
||||
|
||||
/* Frees and removes all values from array */
|
||||
JSON_Status json_array_clear(JSON_Array *array);
|
||||
|
||||
/* Appends new value at the end of array.
|
||||
* json_array_append_value does not copy passed value so it shouldn't be freed afterwards. */
|
||||
JSON_Status json_array_append_value(JSON_Array *array, JSON_Value *value);
|
||||
JSON_Status json_array_append_string(JSON_Array *array, const char *string);
|
||||
JSON_Status json_array_append_number(JSON_Array *array, double number);
|
||||
JSON_Status json_array_append_boolean(JSON_Array *array, int boolean);
|
||||
JSON_Status json_array_append_null(JSON_Array *array);
|
||||
|
||||
/*
|
||||
*JSON Value
|
||||
*/
|
||||
JSON_Value * json_value_init_object (void);
|
||||
JSON_Value * json_value_init_array (void);
|
||||
JSON_Value * json_value_init_string (const char *string); /* copies passed string */
|
||||
JSON_Value * json_value_init_number (double number);
|
||||
JSON_Value * json_value_init_boolean(int boolean);
|
||||
JSON_Value * json_value_init_null (void);
|
||||
JSON_Value * json_value_deep_copy (const JSON_Value *value);
|
||||
void json_value_free (JSON_Value *value);
|
||||
|
||||
JSON_Value_Type json_value_get_type (const JSON_Value *value);
|
||||
JSON_Object * json_value_get_object (const JSON_Value *value);
|
||||
JSON_Array * json_value_get_array (const JSON_Value *value);
|
||||
const char * json_value_get_string (const JSON_Value *value);
|
||||
double json_value_get_number (const JSON_Value *value);
|
||||
int json_value_get_boolean(const JSON_Value *value);
|
||||
|
||||
/* Same as above, but shorter */
|
||||
JSON_Value_Type json_type (const JSON_Value *value);
|
||||
JSON_Object * json_object (const JSON_Value *value);
|
||||
JSON_Array * json_array (const JSON_Value *value);
|
||||
const char * json_string (const JSON_Value *value);
|
||||
double json_number (const JSON_Value *value);
|
||||
int json_boolean(const JSON_Value *value);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,410 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/socket.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/utsname.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "hyper.h"
|
||||
#include "util.h"
|
||||
#include "../config.h"
|
||||
|
||||
int hyper_init_modules()
|
||||
{
|
||||
int status = hyper_cmd("/sbin/depmod");
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "depmod failed, status: %d\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_setup_iptables_rule(struct ipt_rule rule)
|
||||
{
|
||||
char check_cmd[512] = {0};
|
||||
char cmd[512] = {0};
|
||||
int check = -1;
|
||||
|
||||
if (rule.rule != NULL) {
|
||||
sprintf(check_cmd, "/sbin/iptables -t %s -C %s %s", rule.table, rule.chain, rule.rule);
|
||||
sprintf(cmd, "/sbin/iptables -t %s %s %s %s", rule.table, rule.op, rule.chain, rule.rule);
|
||||
} else {
|
||||
sprintf(cmd, "/sbin/iptables -t %s %s %s", rule.table, rule.op, rule.chain);
|
||||
}
|
||||
|
||||
if (strlen(check_cmd) > 0) {
|
||||
check = hyper_cmd(check_cmd);
|
||||
fprintf(stdout, "check iptables '%s', ret: %d\n", check_cmd, check);
|
||||
}
|
||||
|
||||
if (check == 0) {
|
||||
// iptables rule already exist, do not insert it again
|
||||
if (!strncmp(rule.op, "-A", strlen("-A")) ||
|
||||
!strncmp(rule.op, "-I", strlen("-I")) ||
|
||||
!strncmp(rule.op, "-N", strlen("-N"))) {
|
||||
fprintf(stdout, "iptables rule '%s' already exist\n", rule.rule);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int status = hyper_cmd(cmd);
|
||||
fprintf(stdout, "insert iptables '%s', ret: %d\n", cmd, status);
|
||||
if (status != 0) {
|
||||
fprintf(stderr, "insert iptables rule failed, ret: %d\n", status);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// initialize modules and iptables chains
|
||||
int hyper_setup_portmapping(struct hyper_pod *pod)
|
||||
{
|
||||
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
|
||||
pod->portmap_white_lists->e_num == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (hyper_init_modules() < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
// iptables -t filter -N hyperstart-INPUT
|
||||
// iptables -t nat -N hyperstart-PREROUTING
|
||||
// iptables -t filter -I INPUT -j hyperstart-INPUT
|
||||
// iptables -t nat -I PREROUTING -j hyperstart-PREROUTING
|
||||
// iptables -t filter -A hyperstart-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
// iptables -t filter -A hyperstart-INPUT -p icmp -j ACCEPT
|
||||
// iptables -t filter -A hyperstart-INPUT -i lo -j ACCEPT
|
||||
// iptables -t filter -A hyperstart-INPUT -j DROP
|
||||
// iptables -t nat -A hyperstart-PREROUTING -j RETURN
|
||||
const struct ipt_rule rules[] = {
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-N",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = NULL,
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-N",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = NULL,
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-I",
|
||||
.chain = "INPUT",
|
||||
.rule = "-j hyperstart-INPUT",
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-I",
|
||||
.chain = "PREROUTING",
|
||||
.rule = "-j hyperstart-PREROUTING",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-A",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-m state --state RELATED,ESTABLISHED -j ACCEPT",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-A",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-p icmp -j ACCEPT",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-A",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-i lo -j ACCEPT",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-A",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-j DROP",
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-A",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = "-j RETURN",
|
||||
},
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
for(i=0; i< sizeof(rules)/sizeof(struct ipt_rule); i++) {
|
||||
if (hyper_setup_iptables_rule(rules[i])<0) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hyper_cleanup_portmapping(struct hyper_pod *pod)
|
||||
{
|
||||
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
|
||||
pod->portmap_white_lists->e_num == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// iptables -t filter -D hyperstart-INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
|
||||
// iptables -t filter -D hyperstart-INPUT -p icmp -j ACCEPT
|
||||
// iptables -t filter -D hyperstart-INPUT -i lo -j ACCEPT
|
||||
// iptables -t filter -D hyperstart-INPUT -j DROP
|
||||
// iptables -t filter -D INPUT -j hyperstart-DNPUT
|
||||
// iptables -t nat -D hyperstart-PREROUTING -j RETURN
|
||||
// iptables -t nat -D PREROUTING -j hyperstart-PREROUTING
|
||||
// iptables -t filter -F hyperstart-INPUT
|
||||
// iptables -t nat -F hyperstart-PREROUTING
|
||||
// iptables -t filter -X hyperstart-INPUT
|
||||
// iptables -t nat -X hyperstart-PREROUTING
|
||||
const struct ipt_rule rules[] = {
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-m state --state RELATED,ESTABLISHED -j ACCEPT",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-p icmp -j ACCEPT",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-i lo -j ACCEPT",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = "-j DROP",
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = "-j RETURN",
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-D",
|
||||
.chain = "PREROUTING",
|
||||
.rule = "-j hyperstart-PREROUTING",
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "INPUT",
|
||||
.rule = "-j hyperstart-INPUT",
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-F",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = NULL,
|
||||
},
|
||||
{
|
||||
.table = "nat",
|
||||
.op = "-X",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = NULL,
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-F",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = NULL,
|
||||
},
|
||||
{
|
||||
.table = "filter",
|
||||
.op = "-X",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = NULL,
|
||||
},
|
||||
};
|
||||
|
||||
int i = 0;
|
||||
for(i=0; i< sizeof(rules)/sizeof(struct ipt_rule); i++) {
|
||||
if (hyper_setup_iptables_rule(rules[i])<0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
free(pod->portmap_white_lists->internal_networks);
|
||||
free(pod->portmap_white_lists->external_networks);
|
||||
free(pod->portmap_white_lists);
|
||||
pod->portmap_white_lists = NULL;
|
||||
}
|
||||
|
||||
int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod)
|
||||
{
|
||||
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
|
||||
pod->portmap_white_lists->e_num == 0)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (c->ports_num == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i = 0, j = 0;
|
||||
char rule[128] = {0};
|
||||
char *network = NULL;
|
||||
for (i=0; i<c->ports_num; i++) {
|
||||
// setup port mapping only if host_port is set
|
||||
if (c->ports[i].host_port > 0) {
|
||||
for (j=0; j<pod->portmap_white_lists->e_num; j++) {
|
||||
network = pod->portmap_white_lists->external_networks[j];
|
||||
|
||||
// redirect host_port to container_port
|
||||
if (c->ports[i].host_port != c->ports[i].container_port) {
|
||||
sprintf(rule, "-s %s -p %s -m %s --dport %d -j REDIRECT --to-ports %d",
|
||||
network,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].host_port,
|
||||
c->ports[i].container_port);
|
||||
struct ipt_rule redirect_rule = {
|
||||
.table = "nat",
|
||||
.op = "-I",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = rule,
|
||||
};
|
||||
if (hyper_setup_iptables_rule(redirect_rule)<0) {
|
||||
fprintf(stderr, "setup redirect_rule '%s' failed\n", rule);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
// open container_port to external network
|
||||
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
|
||||
network,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].container_port);
|
||||
struct ipt_rule accept_rule = {
|
||||
.table = "filter",
|
||||
.op = "-I",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = rule,
|
||||
};
|
||||
if (hyper_setup_iptables_rule(accept_rule)<0) {
|
||||
fprintf(stderr, "setup accept_rule '%s' failed\n", rule);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// only allow network request from white list
|
||||
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
|
||||
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
|
||||
pod->portmap_white_lists->internal_networks[j],
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].container_port);
|
||||
struct ipt_rule accept_rule = {
|
||||
.table = "filter",
|
||||
.op = "-I",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = rule,
|
||||
};
|
||||
if (hyper_setup_iptables_rule(accept_rule)<0) {
|
||||
fprintf(stderr, "setup accept_rule '%s' failed\n", rule);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod)
|
||||
{
|
||||
if (pod->portmap_white_lists == NULL || (pod->portmap_white_lists->i_num == 0 &&
|
||||
pod->portmap_white_lists->e_num == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (c->ports_num == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
int i = 0, j = 0;
|
||||
char rule[128] = {0};
|
||||
char *network = NULL;
|
||||
for (i=0; i<c->ports_num; i++) {
|
||||
// clean up port mapping only if host_port is set
|
||||
if (c->ports[i].host_port > 0) {
|
||||
for (j=0; j<pod->portmap_white_lists->e_num; j++) {
|
||||
network = pod->portmap_white_lists->external_networks[j];
|
||||
|
||||
// delete rules redirecting host_port to container_port
|
||||
if (c->ports[i].host_port != c->ports[i].container_port) {
|
||||
sprintf(rule, "-s %s -p %s -m %s --dport %d -j REDIRECT --to-ports %d",
|
||||
network,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].host_port,
|
||||
c->ports[i].container_port);
|
||||
struct ipt_rule redirect_rule = {
|
||||
.table = "nat",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-PREROUTING",
|
||||
.rule = rule,
|
||||
};
|
||||
if (hyper_setup_iptables_rule(redirect_rule)<0) {
|
||||
fprintf(stderr, "cleanup redirect '%s' failed\n", rule);
|
||||
}
|
||||
}
|
||||
|
||||
// open container_port to external network
|
||||
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
|
||||
network,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].container_port);
|
||||
struct ipt_rule accept_rule = {
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = rule,
|
||||
};
|
||||
if (hyper_setup_iptables_rule(accept_rule)<0) {
|
||||
fprintf(stderr, "cleanup accept_rule '%s' failed\n", rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (j=0; j<pod->portmap_white_lists->i_num; j++) {
|
||||
sprintf(rule, "-s %s -p %s -m %s --dport %d -j ACCEPT",
|
||||
pod->portmap_white_lists->internal_networks[j],
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].protocol,
|
||||
c->ports[i].container_port);
|
||||
struct ipt_rule accept_rule = {
|
||||
.table = "filter",
|
||||
.op = "-D",
|
||||
.chain = "hyperstart-INPUT",
|
||||
.rule = rule,
|
||||
};
|
||||
if (hyper_setup_iptables_rule(accept_rule)<0) {
|
||||
fprintf(stderr, "cleanup accept_rule '%s' failed\n", rule);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#ifndef _PORT_MAPPING_H_
|
||||
#define _PORT_MAPPING_H_
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
struct ipt_rule {
|
||||
char *table;
|
||||
char *op;
|
||||
char *chain;
|
||||
char *rule;
|
||||
};
|
||||
|
||||
struct hyper_pod;
|
||||
struct hyper_container;
|
||||
int hyper_setup_portmapping(struct hyper_pod *pod);
|
||||
void hyper_cleanup_portmapping(struct hyper_pod *pod);
|
||||
int hyper_setup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod);
|
||||
void hyper_cleanup_container_portmapping(struct hyper_container *c, struct hyper_pod *pod);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,16 @@
|
||||
#define _GNU_SOURCE
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
|
||||
/*
|
||||
* Use raw syscall for versions of glibc that don't include it. But this
|
||||
* requires kernel-headers for syscall number hint.
|
||||
*/
|
||||
|
||||
#if !defined(HAVE_SETNS) && defined(__NR_setns)
|
||||
static inline int setns(int fd, int nstype)
|
||||
{
|
||||
errno = syscall(__NR_setns, fd, nstype);
|
||||
return errno == 0 ? 0 : -1;
|
||||
}
|
||||
#endif
|
||||
+475
-88
@@ -9,19 +9,42 @@
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <mntent.h>
|
||||
#include <sys/wait.h>
|
||||
#include <sys/mount.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/reboot.h>
|
||||
#include <linux/reboot.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
|
||||
#include "net.h"
|
||||
#include "util.h"
|
||||
#include "hyper.h"
|
||||
#include "container.h"
|
||||
#include "../config.h"
|
||||
|
||||
char *read_cmdline(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int hyper_setup_env(struct env *envs, int num)
|
||||
{
|
||||
int i, ret = 0;
|
||||
struct env *env;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
env = &envs[i];
|
||||
if (setenv(env->env, env->value, 1) < 0) {
|
||||
perror("fail to setup env");
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_list_dir(char *path)
|
||||
{
|
||||
struct dirent **list;
|
||||
@@ -38,54 +61,448 @@ int hyper_list_dir(char *path)
|
||||
for (i = 0; i < num; i++) {
|
||||
dir = list[i];
|
||||
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
||||
free(dir);
|
||||
}
|
||||
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_mkdir(char *hyper_path)
|
||||
int hyper_copy_dir(char *src, char *dest)
|
||||
{
|
||||
char cmd[512];
|
||||
snprintf(cmd, sizeof(cmd), "/tar cf - -C %s . | /tar fx - -C %s", src, dest);
|
||||
|
||||
return hyper_cmd(cmd);
|
||||
}
|
||||
|
||||
void hyper_sync_time_hctosys() {
|
||||
int pid;
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fail to fork to copy directory");
|
||||
} else if (pid == 0) {
|
||||
execlp("/busybox", "hwclock", "-s", NULL);
|
||||
perror("exec hwclock -s command failed");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
int hyper_find_sd(char *addr, char **dev)
|
||||
{
|
||||
struct dirent **list;
|
||||
struct dirent *dir;
|
||||
char path[512];
|
||||
int i, num;
|
||||
|
||||
sprintf(path, "/sys/class/scsi_disk/0:0:%s/device/block/", addr);
|
||||
fprintf(stdout, "orig dev %s, scan path %s\n", *dev, path);
|
||||
|
||||
num = scandir(path, &list, NULL, NULL);
|
||||
if (num < 0) {
|
||||
perror("scan path failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
dir = list[i];
|
||||
if (dir->d_name[0] == '.') {
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
||||
*dev = strdup(dir->d_name);
|
||||
break;
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++)
|
||||
free(list[i]);
|
||||
|
||||
free(list);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long id_or_max(const char *name)
|
||||
{
|
||||
char *ptr;
|
||||
long id = strtol(name, &ptr, 10);
|
||||
if (name == ptr || id < 0 || (errno != 0 && id == 0) || *ptr != '\0')
|
||||
return ~0UL;
|
||||
return id;
|
||||
}
|
||||
|
||||
// the same as getpwnam(), but it only parses /etc/passwd and allows name to be id string
|
||||
struct passwd *hyper_getpwnam(const char *name)
|
||||
{
|
||||
uid_t uid = (uid_t)id_or_max(name);
|
||||
FILE *file = fopen("/etc/passwd", "r");
|
||||
if (!file) {
|
||||
perror("faile to open /etc/passwd");
|
||||
return NULL;
|
||||
}
|
||||
for (;;) {
|
||||
struct passwd *pwd = fgetpwent(file);
|
||||
if (!pwd)
|
||||
break;
|
||||
if (!strcmp(pwd->pw_name, name) || pwd->pw_uid == uid) {
|
||||
fclose(file);
|
||||
return pwd;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the same as getgrnam(), but it only parses /etc/group and allows the name to be id string
|
||||
struct group *hyper_getgrnam(const char *name)
|
||||
{
|
||||
gid_t gid = (gid_t)id_or_max(name);
|
||||
FILE *file = fopen("/etc/group", "r");
|
||||
if (!file) {
|
||||
perror("faile to open /etc/group");
|
||||
return NULL;
|
||||
}
|
||||
for (;;) {
|
||||
struct group *gr = fgetgrent(file);
|
||||
if (!gr)
|
||||
break;
|
||||
if (!strcmp(gr->gr_name, name) || gr->gr_gid == gid) {
|
||||
fclose(file);
|
||||
return gr;
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// the same as getgrouplist(), but it only parses /etc/group
|
||||
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups)
|
||||
{
|
||||
int nr = 0, ret;
|
||||
FILE *file = fopen("/etc/group", "r");
|
||||
if (!file) {
|
||||
perror("faile to open /etc/group");
|
||||
return -1;
|
||||
}
|
||||
for (;;) {
|
||||
struct group *gr = fgetgrent(file);
|
||||
if (!gr)
|
||||
break;
|
||||
int j;
|
||||
for (j = 0; gr->gr_mem && gr->gr_mem[j]; j++) {
|
||||
if (!strcmp(gr->gr_mem[j], user)) {
|
||||
if (nr + 1 < *ngroups)
|
||||
groups[nr] = gr->gr_gid;
|
||||
nr++;
|
||||
}
|
||||
}
|
||||
}
|
||||
fclose(file);
|
||||
if (nr == 0) {
|
||||
if (nr + 1 < *ngroups)
|
||||
groups[nr] = group;
|
||||
nr++;
|
||||
}
|
||||
ret = nr <= *ngroups ? nr : -1;
|
||||
*ngroups = nr;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int hyper_write_file(const char *path, const char *value, size_t len)
|
||||
{
|
||||
size_t size = 0, l;
|
||||
int fd = open(path, O_WRONLY);
|
||||
if (fd < 0) {
|
||||
perror("open file failed");
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (size < len) {
|
||||
l = write(fd, value + size, len - size);
|
||||
if (l < 0) {
|
||||
perror("fail to write to file");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
size += l;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Trim all trailing '/' of a hyper_path except for the prefix one. */
|
||||
void hyper_filize(char *hyper_path)
|
||||
{
|
||||
char *p;
|
||||
|
||||
if (strlen(hyper_path) == 0)
|
||||
return;
|
||||
|
||||
p = &hyper_path[strlen(hyper_path) - 1];
|
||||
|
||||
for (; *p == '/' && p != hyper_path; p--) {
|
||||
*p = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
static int hyper_create_parent_dir(const char *hyper_path)
|
||||
{
|
||||
char *p, *path = strdup(hyper_path);
|
||||
int ret = 0;
|
||||
|
||||
if (path == NULL)
|
||||
return -1;
|
||||
p = strrchr(path, '/');
|
||||
if (p != NULL && p != path) {
|
||||
*p = '\0';
|
||||
ret = hyper_mkdir(path, 0777);
|
||||
}
|
||||
free(path);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* hyper_path must point to a file rather than a directory, e.g., having trailing '/' */
|
||||
int hyper_create_file(const char *hyper_path)
|
||||
{
|
||||
int fd;
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(hyper_path, &stbuf) >= 0) {
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
return 0;
|
||||
errno = S_ISDIR(stbuf.st_mode) ? EISDIR : EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hyper_create_parent_dir(hyper_path) < 0)
|
||||
return -1;
|
||||
|
||||
fd = open(hyper_path, O_CREAT|O_WRONLY, 0666);
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
close(fd);
|
||||
fprintf(stdout, "created file %s\n", hyper_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int hyper_mkdir(char *hyper_path, mode_t mode)
|
||||
{
|
||||
struct stat st;
|
||||
char *p, *path = strdup(hyper_path);
|
||||
|
||||
if (path == NULL) {
|
||||
errno = ENOMEM;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fprintf(stdout, "create directory %s\n", path);
|
||||
if (stat(path, &st) >= 0) {
|
||||
if (S_ISDIR(st.st_mode))
|
||||
return 0;
|
||||
goto out;
|
||||
errno = ENOTDIR;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (errno != ENOENT)
|
||||
return -1;
|
||||
goto fail;
|
||||
|
||||
p = strrchr(path, '/');
|
||||
if (p == NULL) {
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (p != path) {
|
||||
*p = '\0';
|
||||
|
||||
if (hyper_mkdir(path) < 0)
|
||||
return -1;
|
||||
if (hyper_mkdir(path, mode) < 0)
|
||||
goto fail;
|
||||
|
||||
*p = '/';
|
||||
}
|
||||
|
||||
if (mkdir(path, 0755) < 0 && errno != EEXIST)
|
||||
return -1;
|
||||
|
||||
fprintf(stdout, "create directory %s\n", path);
|
||||
if (mkdir(path, mode) < 0 && errno != EEXIST) {
|
||||
perror("failed to create directory");
|
||||
goto fail;
|
||||
}
|
||||
out:
|
||||
free(path);
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
free(path);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void online_cpu(void)
|
||||
{
|
||||
DIR *dir = opendir("/sys/devices/system/cpu");
|
||||
if (dir == NULL) {
|
||||
fprintf(stderr, "open dir /sys/devices/system/cpu failed\n");
|
||||
return;
|
||||
}
|
||||
printf("online_cpu()\n");
|
||||
for (;;) {
|
||||
int num;
|
||||
int ret;
|
||||
char path[256];
|
||||
int fd;
|
||||
|
||||
struct dirent *entry = readdir(dir);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
if (entry->d_type != DT_DIR)
|
||||
continue;
|
||||
ret = sscanf(entry->d_name, "cpu%d", &num);
|
||||
if (ret < 1 || num == 0) /* skip none cpu%d and cpu0 */
|
||||
continue;
|
||||
sprintf(path, "/sys/devices/system/cpu/%s/online", entry->d_name);
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "open %s failed\n", path);
|
||||
continue;
|
||||
}
|
||||
printf("try to online %s\n", entry->d_name);
|
||||
ret = write(fd, "1", sizeof("1"));
|
||||
printf("online %s result: %s\n", entry->d_name, ret == 2 ? "success" : "failed");
|
||||
close(fd);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
void online_memory(void)
|
||||
{
|
||||
DIR *dir = opendir("/sys/devices/system/memory");
|
||||
if (dir == NULL) {
|
||||
fprintf(stderr, "open dir /sys/devices/system/memory failed\n");
|
||||
return;
|
||||
}
|
||||
printf("online_memory()\n");
|
||||
for (;;) {
|
||||
int num;
|
||||
int ret;
|
||||
char path[256];
|
||||
int fd;
|
||||
|
||||
struct dirent *entry = readdir(dir);
|
||||
if (entry == NULL)
|
||||
break;
|
||||
if (entry->d_type != DT_DIR)
|
||||
continue;
|
||||
ret = sscanf(entry->d_name, "memory%d", &num);
|
||||
if (ret < 1 || num == 0) /* skip none memory%d and memory0 */
|
||||
continue;
|
||||
sprintf(path, "/sys/devices/system/memory/%s/online", entry->d_name);
|
||||
fd = open(path, O_RDWR);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "open %s failed\n", path);
|
||||
continue;
|
||||
}
|
||||
printf("try to online %s\n", entry->d_name);
|
||||
ret = write(fd, "1", sizeof("1"));
|
||||
printf("online %s result: %s\n", entry->d_name, ret == 2 ? "success" : "failed");
|
||||
close(fd);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
#if WITH_VBOX
|
||||
|
||||
#include <termios.h>
|
||||
int hyper_open_channel(char *channel, int mode)
|
||||
{
|
||||
struct termios term;
|
||||
int fd = open(channel, O_RDWR | O_CLOEXEC | mode);
|
||||
fprintf(stdout, "open %s get %d\n", channel, fd);
|
||||
|
||||
if (fd < 0) {
|
||||
perror("fail to open channel device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(&term, sizeof(term));
|
||||
|
||||
cfmakeraw(&term);
|
||||
term.c_cflag |= CLOCAL | CREAD| CRTSCTS;
|
||||
term.c_cc[VTIME] = 0;
|
||||
term.c_cc[VMIN] = 0;
|
||||
|
||||
cfsetispeed(&term, B115200);
|
||||
cfsetospeed(&term, B115200);
|
||||
|
||||
tcsetattr(fd, TCSANOW, &term);
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static const char *moderror(int err)
|
||||
{
|
||||
switch (err) {
|
||||
case ENOEXEC:
|
||||
return "Invalid module format";
|
||||
case ENOENT:
|
||||
return "Unknown symbol in module";
|
||||
case ESRCH:
|
||||
return "Module has wrong symbol version";
|
||||
case EINVAL:
|
||||
return "Invalid parameters";
|
||||
default:
|
||||
return strerror(err);
|
||||
}
|
||||
}
|
||||
|
||||
extern long init_module (void *, unsigned long, const char *);
|
||||
|
||||
int hyper_insmod(char *module)
|
||||
{
|
||||
size_t size, offset = 0, rc;
|
||||
struct stat st;
|
||||
char *buf = NULL;
|
||||
int ret;
|
||||
|
||||
int fd = open(module, O_RDONLY);
|
||||
if (fd == -1) {
|
||||
fprintf (stderr, "insmod: open: %s: %m\n", module);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fstat(fd, &st) == -1) {
|
||||
perror ("insmod: fstat");
|
||||
goto err;
|
||||
}
|
||||
|
||||
size = st.st_size;
|
||||
buf = malloc(size);
|
||||
if (buf == NULL)
|
||||
goto err;
|
||||
|
||||
do {
|
||||
rc = read(fd, buf + offset, size - offset);
|
||||
if (rc == -1) {
|
||||
perror ("insmod: read");
|
||||
goto err;
|
||||
}
|
||||
offset += rc;
|
||||
} while (offset < size);
|
||||
|
||||
if (init_module(buf, size, "") != 0) {
|
||||
fprintf (stderr, "insmod: init_module: %s: %s\n", module, moderror(errno));
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 0;
|
||||
out:
|
||||
close(fd);
|
||||
free(buf);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
ret = -1;
|
||||
goto out;
|
||||
}
|
||||
#else
|
||||
int hyper_open_channel(char *channel, int mode)
|
||||
{
|
||||
struct dirent **list;
|
||||
@@ -133,7 +550,7 @@ int hyper_open_channel(char *channel, int mode)
|
||||
fprintf(stdout, "open hyper channel %s\n", path);
|
||||
fd = open(path, O_RDWR | O_CLOEXEC | mode);
|
||||
if (fd < 0)
|
||||
perror("fail to open channel deice");
|
||||
perror("fail to open channel device");
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -142,34 +559,22 @@ int hyper_open_channel(char *channel, int mode)
|
||||
return fd;
|
||||
}
|
||||
|
||||
int hyper_insmod(char *module)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
int hyper_open_serial_dev(char *tty)
|
||||
{
|
||||
int fd = open(tty, O_RDWR | O_CLOEXEC | O_NOCTTY);
|
||||
|
||||
if (fd < 0) {
|
||||
if (fd < 0)
|
||||
perror("fail to open tty device");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
int hyper_open_serial(char *tty)
|
||||
{
|
||||
char path[256];
|
||||
|
||||
memset(path, 0, sizeof(path));
|
||||
|
||||
if (snprintf(path, sizeof(path), "/dev/%s", tty) < 0) {
|
||||
fprintf(stderr, "get channel device %s path failed\n", tty);
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stdout, "open hyper tty %s\n", path);
|
||||
|
||||
return hyper_open_serial_dev(path);
|
||||
}
|
||||
|
||||
int hyper_setfd_cloexec(int fd)
|
||||
{
|
||||
int flags = fcntl(fd, F_GETFD);
|
||||
@@ -201,7 +606,7 @@ int hyper_setfd_block(int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return flags;
|
||||
}
|
||||
|
||||
int hyper_setfd_nonblock(int fd)
|
||||
@@ -218,10 +623,10 @@ int hyper_setfd_nonblock(int fd)
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
return flags;
|
||||
}
|
||||
|
||||
void hyper_unmount_all(void)
|
||||
static void hyper_unmount_all(void)
|
||||
{
|
||||
FILE *mtab;
|
||||
struct mntent *mnt;
|
||||
@@ -261,64 +666,46 @@ void hyper_unmount_all(void)
|
||||
fprintf(stdout, ("umount %s: %s failed\n"),
|
||||
filesys, strerror(errno));
|
||||
}
|
||||
free(filesys);
|
||||
mntlist[i] = NULL;
|
||||
}
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
void hyper_kill_all(void)
|
||||
void hyper_shutdown(int error)
|
||||
{
|
||||
int npids = 0;
|
||||
int index = 0;
|
||||
int pid;
|
||||
DIR *dp;
|
||||
struct dirent *de;
|
||||
pid_t *pids = NULL;
|
||||
|
||||
dp = opendir("/proc");
|
||||
if (dp == NULL)
|
||||
return;
|
||||
|
||||
while ((de = readdir(dp)) && de != NULL) {
|
||||
if (!isdigit(de->d_name[0]))
|
||||
continue;
|
||||
pid = atoi(de->d_name);
|
||||
if (pid == 1)
|
||||
continue;
|
||||
if (index <= npids) {
|
||||
pids = realloc(pids, npids + 16384);
|
||||
if (pids == NULL)
|
||||
return;
|
||||
npids += 16384;
|
||||
}
|
||||
|
||||
pids[index++] = pid;
|
||||
}
|
||||
|
||||
fprintf(stdout, "Sending SIGTERM\n");
|
||||
|
||||
for (--index; index >= 0; --index) {
|
||||
fprintf(stdout, "kill process %d\n", pids[index]);
|
||||
kill(pids[index], SIGTERM);
|
||||
}
|
||||
|
||||
free(pids);
|
||||
closedir(dp);
|
||||
}
|
||||
|
||||
void hyper_shutdown(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);
|
||||
|
||||
hyper_send_msg(ctl.chan.fd, FINISH, pod->c_num * 4, data);
|
||||
|
||||
hyper_kill_all();
|
||||
|
||||
hyper_send_msg_block(ctl.chan.fd, error?ERROR:ACK, 0, NULL);
|
||||
hyper_unmount_all();
|
||||
|
||||
reboot(LINUX_REBOOT_CMD_POWER_OFF);
|
||||
}
|
||||
|
||||
int hyper_cmd(char *cmd)
|
||||
{
|
||||
int pid, status;
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
perror("fail to fork");
|
||||
return -1;
|
||||
} else if (pid > 0) {
|
||||
if (waitpid(pid, &status, 0) <= 0) {
|
||||
perror("waiting fork cmd failed");
|
||||
return -1;
|
||||
}
|
||||
if (WIFEXITED(status)) {
|
||||
int ret = WEXITSTATUS(status);
|
||||
fprintf(stdout, "%s cmd exit normally, status %" PRIu8 "\n", cmd, ret);
|
||||
if (ret == 0)
|
||||
return 0;
|
||||
}
|
||||
|
||||
fprintf(stdout, "cmd %s exit unexpectedly, status %" PRIu8 "\n", cmd, status);
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stdout, "executing cmd %s\n", cmd);
|
||||
execlp("/busybox", "sh", "-c", cmd, NULL);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
+31
-6
@@ -1,18 +1,43 @@
|
||||
#ifndef _UTIL_H_
|
||||
#define _UTIL_H_
|
||||
|
||||
#include "hyper.h"
|
||||
#include <stdio.h>
|
||||
#include <grp.h>
|
||||
#include <pwd.h>
|
||||
#include "../config.h"
|
||||
|
||||
struct hyper_pod;
|
||||
struct env;
|
||||
|
||||
#ifdef WITH_DEBUG
|
||||
#define dprintf(fmt, ...) \
|
||||
fprintf(stdout, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define dprintf(fmr, ...)
|
||||
#endif
|
||||
|
||||
char *read_cmdline(void);
|
||||
int hyper_setup_env(struct env *envs, int num);
|
||||
int hyper_find_sd(char *addr, char **dev);
|
||||
int hyper_list_dir(char *path);
|
||||
int hyper_mkdir(char *path);
|
||||
int hyper_copy_dir(char *src, char *dst);
|
||||
void hyper_sync_time_hctosys();
|
||||
void online_cpu(void);
|
||||
void online_memory(void);
|
||||
int hyper_cmd(char *cmd);
|
||||
int hyper_create_file(const char *hyper_path);
|
||||
void hyper_filize(char *hyper_path);
|
||||
int hyper_mkdir(char *path, mode_t mode);
|
||||
int hyper_write_file(const char *path, const char *value, size_t len);
|
||||
int hyper_open_channel(char *channel, int mode);
|
||||
int hyper_open_serial_dev(char *tty);
|
||||
int hyper_open_serial(char *tty);
|
||||
int hyper_setfd_cloexec(int fd);
|
||||
int hyper_setfd_block(int fd);
|
||||
int hyper_setfd_nonblock(int fd);
|
||||
void hyper_shutdown(struct hyper_pod *pod);
|
||||
void hyper_kill_all(void);
|
||||
void hyper_unmount_all(void);
|
||||
int hyper_socketpair(int domain, int type, int protocol, int sv[2]);
|
||||
void hyper_shutdown(int ack);
|
||||
int hyper_insmod(char *module);
|
||||
struct passwd *hyper_getpwnam(const char *name);
|
||||
struct group *hyper_getgrnam(const char *name);
|
||||
int hyper_getgrouplist(const char *user, gid_t group, gid_t *groups, int *ngroups);
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user