mirror of
https://github.com/clearlinux/hyperstart.git
synced 2026-09-06 13:41:44 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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,7 +10,9 @@
|
|||||||
init
|
init
|
||||||
build/hyper_daemon
|
build/hyper_daemon
|
||||||
build/hyper-initrd.img
|
build/hyper-initrd.img
|
||||||
|
build/cbfs.rom
|
||||||
build/root/*
|
build/root/*
|
||||||
|
build/*iso
|
||||||
build/daemon
|
build/daemon
|
||||||
build/.*
|
build/.*
|
||||||
src/.*
|
src/.*
|
||||||
|
|||||||
@@ -1 +1,6 @@
|
|||||||
SUBDIRS=src build
|
SUBDIRS=src build
|
||||||
|
|
||||||
|
initrd-local:
|
||||||
|
@echo finish make initrd
|
||||||
|
cbfs-local:
|
||||||
|
@echo finish make cbfs
|
||||||
|
|||||||
@@ -1,13 +1,21 @@
|
|||||||
# The init Task for Hyper
|
# The init Task for Hyper
|
||||||
|
|
||||||
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 Hyper and HyperStart through [The Hyper Page](https://github.com/hyperhq/hyper)
|
||||||
|
|
||||||
## Build from source
|
## Build from source
|
||||||
|
|
||||||
clone this repo, and make sure have build-essentials installed. Go into the working copy and
|
clone this repo, and make sure you have build-essentials installed. Go into the working copy and
|
||||||
|
|
||||||
> ./autogen.sh
|
> ./autogen.sh
|
||||||
> ./configure
|
> ./configure
|
||||||
> make
|
> make
|
||||||
|
|
||||||
Then you can find `hyper-initrd.img` in build directory, together with a pre-build kernel.
|
Then you can find `hyper-initrd.img` in the build directory, together with a pre-built kernel.
|
||||||
|
|
||||||
|
If you want to get the boot disk file for 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.
|
||||||
|
|||||||
+8
-3
@@ -1,7 +1,12 @@
|
|||||||
bin_PROGRAMS=hyper_daemon
|
all-local: initrd
|
||||||
hyper_daemon_SOURCES=hyper_daemon.c ../src/net.c
|
|
||||||
all-local:
|
if WITH_VBOX
|
||||||
|
initrd-local:
|
||||||
|
bash ./make-initrd.sh vbox
|
||||||
|
else
|
||||||
|
initrd-local:
|
||||||
bash ./make-initrd.sh
|
bash ./make-initrd.sh
|
||||||
|
endif
|
||||||
|
|
||||||
cbfs-local:
|
cbfs-local:
|
||||||
bash ./make-initrd.sh cbfs
|
bash ./make-initrd.sh cbfs
|
||||||
|
|||||||
@@ -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;
|
|
||||||
}
|
|
||||||
Binary file not shown.
+75
-35
@@ -432,9 +432,7 @@ CONFIG_GENERIC_EARLY_IOREMAP=y
|
|||||||
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
|
# CONFIG_X86_CHECK_BIOS_CORRUPTION is not set
|
||||||
CONFIG_X86_RESERVE_LOW=64
|
CONFIG_X86_RESERVE_LOW=64
|
||||||
CONFIG_MTRR=y
|
CONFIG_MTRR=y
|
||||||
CONFIG_MTRR_SANITIZER=y
|
# CONFIG_MTRR_SANITIZER is not set
|
||||||
CONFIG_MTRR_SANITIZER_ENABLE_DEFAULT=0
|
|
||||||
CONFIG_MTRR_SANITIZER_SPARE_REG_NR_DEFAULT=1
|
|
||||||
CONFIG_X86_PAT=y
|
CONFIG_X86_PAT=y
|
||||||
CONFIG_ARCH_USES_PG_UNCACHED=y
|
CONFIG_ARCH_USES_PG_UNCACHED=y
|
||||||
CONFIG_ARCH_RANDOM=y
|
CONFIG_ARCH_RANDOM=y
|
||||||
@@ -585,11 +583,7 @@ CONFIG_PACKET=y
|
|||||||
# CONFIG_PACKET_DIAG is not set
|
# CONFIG_PACKET_DIAG is not set
|
||||||
CONFIG_UNIX=y
|
CONFIG_UNIX=y
|
||||||
# CONFIG_UNIX_DIAG is not set
|
# CONFIG_UNIX_DIAG is not set
|
||||||
CONFIG_XFRM=y
|
|
||||||
# CONFIG_XFRM_USER is not set
|
# CONFIG_XFRM_USER is not set
|
||||||
# CONFIG_XFRM_SUB_POLICY is not set
|
|
||||||
# CONFIG_XFRM_MIGRATE is not set
|
|
||||||
# CONFIG_XFRM_STATISTICS is not set
|
|
||||||
# CONFIG_NET_KEY is not set
|
# CONFIG_NET_KEY is not set
|
||||||
CONFIG_INET=y
|
CONFIG_INET=y
|
||||||
# CONFIG_IP_MULTICAST is not set
|
# CONFIG_IP_MULTICAST is not set
|
||||||
@@ -597,17 +591,16 @@ CONFIG_INET=y
|
|||||||
# CONFIG_IP_PNP is not set
|
# CONFIG_IP_PNP is not set
|
||||||
# CONFIG_NET_IPIP is not set
|
# CONFIG_NET_IPIP is not set
|
||||||
# CONFIG_NET_IPGRE_DEMUX is not set
|
# CONFIG_NET_IPGRE_DEMUX is not set
|
||||||
CONFIG_NET_IP_TUNNEL=y
|
# CONFIG_NET_IP_TUNNEL is not set
|
||||||
# CONFIG_SYN_COOKIES is not set
|
# CONFIG_SYN_COOKIES is not set
|
||||||
# CONFIG_NET_UDP_TUNNEL is not set
|
# CONFIG_NET_UDP_TUNNEL is not set
|
||||||
# CONFIG_NET_FOU is not set
|
# CONFIG_NET_FOU is not set
|
||||||
# CONFIG_NET_FOU_IP_TUNNELS is not set
|
|
||||||
# CONFIG_GENEVE is not set
|
# CONFIG_GENEVE is not set
|
||||||
# CONFIG_INET_AH is not set
|
# CONFIG_INET_AH is not set
|
||||||
# CONFIG_INET_ESP is not set
|
# CONFIG_INET_ESP is not set
|
||||||
# CONFIG_INET_IPCOMP is not set
|
# CONFIG_INET_IPCOMP is not set
|
||||||
# CONFIG_INET_XFRM_TUNNEL is not set
|
# CONFIG_INET_XFRM_TUNNEL is not set
|
||||||
CONFIG_INET_TUNNEL=y
|
# CONFIG_INET_TUNNEL is not set
|
||||||
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
|
# CONFIG_INET_XFRM_MODE_TRANSPORT is not set
|
||||||
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
|
# CONFIG_INET_XFRM_MODE_TUNNEL is not set
|
||||||
# CONFIG_INET_XFRM_MODE_BEET is not set
|
# CONFIG_INET_XFRM_MODE_BEET is not set
|
||||||
@@ -626,14 +619,11 @@ CONFIG_IPV6=y
|
|||||||
# CONFIG_IPV6_MIP6 is not set
|
# CONFIG_IPV6_MIP6 is not set
|
||||||
# CONFIG_INET6_XFRM_TUNNEL is not set
|
# CONFIG_INET6_XFRM_TUNNEL is not set
|
||||||
# CONFIG_INET6_TUNNEL is not set
|
# CONFIG_INET6_TUNNEL is not set
|
||||||
CONFIG_INET6_XFRM_MODE_TRANSPORT=y
|
# CONFIG_INET6_XFRM_MODE_TRANSPORT is not set
|
||||||
CONFIG_INET6_XFRM_MODE_TUNNEL=y
|
# CONFIG_INET6_XFRM_MODE_TUNNEL is not set
|
||||||
CONFIG_INET6_XFRM_MODE_BEET=y
|
# CONFIG_INET6_XFRM_MODE_BEET is not set
|
||||||
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
|
# CONFIG_INET6_XFRM_MODE_ROUTEOPTIMIZATION is not set
|
||||||
# CONFIG_IPV6_VTI is not set
|
# CONFIG_IPV6_SIT is not set
|
||||||
CONFIG_IPV6_SIT=y
|
|
||||||
# CONFIG_IPV6_SIT_6RD is not set
|
|
||||||
CONFIG_IPV6_NDISC_NODETYPE=y
|
|
||||||
# CONFIG_IPV6_TUNNEL is not set
|
# CONFIG_IPV6_TUNNEL is not set
|
||||||
# CONFIG_IPV6_GRE is not set
|
# CONFIG_IPV6_GRE is not set
|
||||||
# CONFIG_IPV6_MULTIPLE_TABLES is not set
|
# CONFIG_IPV6_MULTIPLE_TABLES is not set
|
||||||
@@ -730,7 +720,7 @@ CONFIG_GENERIC_CPU_AUTOPROBE=y
|
|||||||
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
|
CONFIG_ARCH_MIGHT_HAVE_PC_PARPORT=y
|
||||||
# CONFIG_PARPORT is not set
|
# CONFIG_PARPORT is not set
|
||||||
CONFIG_PNP=y
|
CONFIG_PNP=y
|
||||||
CONFIG_PNP_DEBUG_MESSAGES=y
|
# CONFIG_PNP_DEBUG_MESSAGES is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Protocols
|
# Protocols
|
||||||
@@ -758,7 +748,6 @@ CONFIG_BLK_DEV_RAM_SIZE=16384
|
|||||||
# CONFIG_CDROM_PKTCDVD is not set
|
# CONFIG_CDROM_PKTCDVD is not set
|
||||||
# CONFIG_ATA_OVER_ETH is not set
|
# CONFIG_ATA_OVER_ETH is not set
|
||||||
CONFIG_XEN_BLKDEV_FRONTEND=y
|
CONFIG_XEN_BLKDEV_FRONTEND=y
|
||||||
# CONFIG_XEN_BLKDEV_BACKEND is not set
|
|
||||||
CONFIG_VIRTIO_BLK=y
|
CONFIG_VIRTIO_BLK=y
|
||||||
# CONFIG_BLK_DEV_HD is not set
|
# CONFIG_BLK_DEV_HD is not set
|
||||||
# CONFIG_BLK_DEV_RBD is not set
|
# CONFIG_BLK_DEV_RBD is not set
|
||||||
@@ -943,7 +932,69 @@ CONFIG_VIRTIO_NET=y
|
|||||||
# CONFIG_NET_DSA_MV88E6171 is not set
|
# CONFIG_NET_DSA_MV88E6171 is not set
|
||||||
# CONFIG_NET_DSA_MV88E6352 is not set
|
# CONFIG_NET_DSA_MV88E6352 is not set
|
||||||
# CONFIG_NET_DSA_BCM_SF2 is not set
|
# CONFIG_NET_DSA_BCM_SF2 is not set
|
||||||
# CONFIG_ETHERNET is not set
|
CONFIG_ETHERNET=y
|
||||||
|
# CONFIG_NET_VENDOR_3COM is not set
|
||||||
|
# CONFIG_NET_VENDOR_ADAPTEC is not set
|
||||||
|
# CONFIG_NET_VENDOR_AGERE is not set
|
||||||
|
# CONFIG_NET_VENDOR_ALTEON is not set
|
||||||
|
# CONFIG_ALTERA_TSE is not set
|
||||||
|
# CONFIG_NET_VENDOR_AMD is not set
|
||||||
|
# CONFIG_NET_XGENE is not set
|
||||||
|
# CONFIG_NET_VENDOR_ARC is not set
|
||||||
|
# CONFIG_NET_VENDOR_ATHEROS is not set
|
||||||
|
# CONFIG_NET_VENDOR_BROADCOM is not set
|
||||||
|
# CONFIG_NET_VENDOR_BROCADE is not set
|
||||||
|
# CONFIG_NET_VENDOR_CHELSIO is not set
|
||||||
|
# CONFIG_NET_VENDOR_CISCO is not set
|
||||||
|
# CONFIG_CX_ECAT is not set
|
||||||
|
# CONFIG_DNET is not set
|
||||||
|
# CONFIG_NET_VENDOR_DEC is not set
|
||||||
|
# CONFIG_NET_VENDOR_DLINK is not set
|
||||||
|
# CONFIG_NET_VENDOR_EMULEX is not set
|
||||||
|
# CONFIG_NET_VENDOR_EXAR is not set
|
||||||
|
# CONFIG_NET_VENDOR_HP is not set
|
||||||
|
CONFIG_NET_VENDOR_INTEL=y
|
||||||
|
# CONFIG_E100 is not set
|
||||||
|
CONFIG_E1000=y
|
||||||
|
# CONFIG_E1000E is not set
|
||||||
|
# CONFIG_IGB is not set
|
||||||
|
# CONFIG_IGBVF is not set
|
||||||
|
# CONFIG_IXGB is not set
|
||||||
|
# CONFIG_IXGBE is not set
|
||||||
|
# CONFIG_IXGBEVF is not set
|
||||||
|
# CONFIG_I40E is not set
|
||||||
|
# CONFIG_I40EVF is not set
|
||||||
|
# CONFIG_FM10K is not set
|
||||||
|
# CONFIG_NET_VENDOR_I825XX is not set
|
||||||
|
# CONFIG_IP1000 is not set
|
||||||
|
# CONFIG_JME is not set
|
||||||
|
# CONFIG_NET_VENDOR_MARVELL is not set
|
||||||
|
# CONFIG_NET_VENDOR_MELLANOX is not set
|
||||||
|
# CONFIG_NET_VENDOR_MICREL is not set
|
||||||
|
# CONFIG_NET_VENDOR_MYRI is not set
|
||||||
|
# CONFIG_FEALNX is not set
|
||||||
|
# CONFIG_NET_VENDOR_NATSEMI is not set
|
||||||
|
# CONFIG_NET_VENDOR_NVIDIA is not set
|
||||||
|
# CONFIG_NET_VENDOR_OKI is not set
|
||||||
|
# CONFIG_ETHOC is not set
|
||||||
|
# CONFIG_NET_PACKET_ENGINE is not set
|
||||||
|
# CONFIG_NET_VENDOR_QLOGIC is not set
|
||||||
|
# CONFIG_NET_VENDOR_QUALCOMM is not set
|
||||||
|
# CONFIG_NET_VENDOR_REALTEK is not set
|
||||||
|
# CONFIG_NET_VENDOR_RDC is not set
|
||||||
|
# CONFIG_NET_VENDOR_ROCKER is not set
|
||||||
|
# CONFIG_NET_VENDOR_SAMSUNG is not set
|
||||||
|
# CONFIG_NET_VENDOR_SEEQ is not set
|
||||||
|
# CONFIG_NET_VENDOR_SILAN is not set
|
||||||
|
# CONFIG_NET_VENDOR_SIS is not set
|
||||||
|
# CONFIG_SFC is not set
|
||||||
|
# CONFIG_NET_VENDOR_SMSC is not set
|
||||||
|
# CONFIG_NET_VENDOR_STMICRO is not set
|
||||||
|
# CONFIG_NET_VENDOR_SUN is not set
|
||||||
|
# CONFIG_NET_VENDOR_TEHUTI is not set
|
||||||
|
# CONFIG_NET_VENDOR_TI is not set
|
||||||
|
# CONFIG_NET_VENDOR_VIA is not set
|
||||||
|
# CONFIG_NET_VENDOR_WIZNET is not set
|
||||||
# CONFIG_FDDI is not set
|
# CONFIG_FDDI is not set
|
||||||
# CONFIG_HIPPI is not set
|
# CONFIG_HIPPI is not set
|
||||||
# CONFIG_NET_SB1000 is not set
|
# CONFIG_NET_SB1000 is not set
|
||||||
@@ -961,7 +1012,6 @@ CONFIG_VIRTIO_NET=y
|
|||||||
#
|
#
|
||||||
# CONFIG_WAN is not set
|
# CONFIG_WAN is not set
|
||||||
CONFIG_XEN_NETDEV_FRONTEND=y
|
CONFIG_XEN_NETDEV_FRONTEND=y
|
||||||
# CONFIG_XEN_NETDEV_BACKEND is not set
|
|
||||||
# CONFIG_VMXNET3 is not set
|
# CONFIG_VMXNET3 is not set
|
||||||
# CONFIG_ISDN is not set
|
# CONFIG_ISDN is not set
|
||||||
|
|
||||||
@@ -995,17 +1045,8 @@ CONFIG_INPUT=y
|
|||||||
#
|
#
|
||||||
# Hardware I/O ports
|
# Hardware I/O ports
|
||||||
#
|
#
|
||||||
CONFIG_SERIO=y
|
# CONFIG_SERIO is not set
|
||||||
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
|
CONFIG_ARCH_MIGHT_HAVE_PC_SERIO=y
|
||||||
CONFIG_SERIO_I8042=y
|
|
||||||
CONFIG_SERIO_SERPORT=y
|
|
||||||
# CONFIG_SERIO_CT82C710 is not set
|
|
||||||
# CONFIG_SERIO_PCIPS2 is not set
|
|
||||||
CONFIG_SERIO_LIBPS2=y
|
|
||||||
CONFIG_SERIO_RAW=m
|
|
||||||
# CONFIG_SERIO_ALTERA_PS2 is not set
|
|
||||||
# CONFIG_SERIO_PS2MULT is not set
|
|
||||||
# CONFIG_SERIO_ARC_PS2 is not set
|
|
||||||
# CONFIG_GAMEPORT is not set
|
# CONFIG_GAMEPORT is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
@@ -1216,14 +1257,13 @@ CONFIG_VIRTIO_MMIO_CMDLINE_DEVICES=y
|
|||||||
#
|
#
|
||||||
# CONFIG_XEN_BALLOON is not set
|
# CONFIG_XEN_BALLOON is not set
|
||||||
# CONFIG_XEN_DEV_EVTCHN is not set
|
# CONFIG_XEN_DEV_EVTCHN is not set
|
||||||
CONFIG_XEN_BACKEND=y
|
# CONFIG_XEN_BACKEND is not set
|
||||||
# CONFIG_XENFS is not set
|
# CONFIG_XENFS is not set
|
||||||
# CONFIG_XEN_SYS_HYPERVISOR is not set
|
# CONFIG_XEN_SYS_HYPERVISOR is not set
|
||||||
CONFIG_XEN_XENBUS_FRONTEND=y
|
CONFIG_XEN_XENBUS_FRONTEND=y
|
||||||
# CONFIG_XEN_GNTDEV is not set
|
# CONFIG_XEN_GNTDEV is not set
|
||||||
# CONFIG_XEN_GRANT_DEV_ALLOC is not set
|
# CONFIG_XEN_GRANT_DEV_ALLOC is not set
|
||||||
CONFIG_SWIOTLB_XEN=y
|
CONFIG_SWIOTLB_XEN=y
|
||||||
CONFIG_XEN_PCIDEV_BACKEND=m
|
|
||||||
CONFIG_XEN_PRIVCMD=m
|
CONFIG_XEN_PRIVCMD=m
|
||||||
CONFIG_XEN_HAVE_PVMMU=y
|
CONFIG_XEN_HAVE_PVMMU=y
|
||||||
# CONFIG_STAGING is not set
|
# CONFIG_STAGING is not set
|
||||||
@@ -1385,7 +1425,7 @@ CONFIG_9P_FS_POSIX_ACL=y
|
|||||||
CONFIG_9P_FS_SECURITY=y
|
CONFIG_9P_FS_SECURITY=y
|
||||||
CONFIG_NLS=y
|
CONFIG_NLS=y
|
||||||
CONFIG_NLS_DEFAULT="utf8"
|
CONFIG_NLS_DEFAULT="utf8"
|
||||||
CONFIG_NLS_CODEPAGE_437=m
|
# CONFIG_NLS_CODEPAGE_437 is not set
|
||||||
# CONFIG_NLS_CODEPAGE_737 is not set
|
# CONFIG_NLS_CODEPAGE_737 is not set
|
||||||
# CONFIG_NLS_CODEPAGE_775 is not set
|
# CONFIG_NLS_CODEPAGE_775 is not set
|
||||||
# CONFIG_NLS_CODEPAGE_850 is not set
|
# CONFIG_NLS_CODEPAGE_850 is not set
|
||||||
@@ -1433,7 +1473,7 @@ CONFIG_NLS_CODEPAGE_437=m
|
|||||||
# CONFIG_NLS_MAC_INUIT is not set
|
# CONFIG_NLS_MAC_INUIT is not set
|
||||||
# CONFIG_NLS_MAC_ROMANIAN is not set
|
# CONFIG_NLS_MAC_ROMANIAN is not set
|
||||||
# CONFIG_NLS_MAC_TURKISH is not set
|
# CONFIG_NLS_MAC_TURKISH is not set
|
||||||
CONFIG_NLS_UTF8=m
|
# CONFIG_NLS_UTF8 is not set
|
||||||
|
|
||||||
#
|
#
|
||||||
# Kernel hacking
|
# Kernel hacking
|
||||||
|
|||||||
+46
-12
@@ -18,23 +18,57 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$1"x = "vbox"x ]; then
|
||||||
|
echo "build initrd for vbox"
|
||||||
|
cp ./vbox/driver/* ./root
|
||||||
|
fi
|
||||||
|
|
||||||
cd ./root && find . | cpio -H newc -o | gzip -9 > ../hyper-initrd.img
|
cd ./root && find . | cpio -H newc -o | gzip -9 > ../hyper-initrd.img
|
||||||
|
|
||||||
|
cd ../
|
||||||
|
rm -rf ./root
|
||||||
|
|
||||||
if [ "$1" != "cbfs" ]; then
|
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 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
|
||||||
|
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
|
exit 0
|
||||||
fi
|
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"
|
cd tmp
|
||||||
rm -rf .cbfs
|
cp ../vbox/kernel ./kernel/
|
||||||
rm -rf cbfs.rom
|
cp ../hyper-initrd.img ./images/initrd.img
|
||||||
|
cp ../vbox/isolinux/isolinux.bin ./isolinux/
|
||||||
|
cp ../vbox/isolinux/ldlinux.c32 ./isolinux/
|
||||||
|
|
||||||
mkdir .cbfs
|
cat > isolinux/syslinux.cfg <<EOF
|
||||||
dd if=/dev/zero of=.cbfs/boot.bin bs=4096 count=1
|
DEFAULT linux
|
||||||
cbfstool .cbfs/cbfs.rom create -s 4096k -B .cbfs/boot.bin -m x86 0x1000
|
LABEL linux
|
||||||
cbfstool .cbfs/cbfs.rom add -f kernel -n vmlinuz -t raw
|
SAY Now booting the kernel from SYSLINUX...
|
||||||
cbfstool .cbfs/cbfs.rom add -f hyper-initrd.img -n initrd -t raw
|
KERNEL /kernel/kernel
|
||||||
cp .cbfs/cbfs.rom ./
|
APPEND initrd=/images/initrd.img
|
||||||
rm -rf .cbfs
|
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.
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.
|
# Process this file with autoconf to produce a configure script.
|
||||||
|
|
||||||
AC_PREREQ([2.69])
|
AC_PREREQ([2.69])
|
||||||
AC_INIT([hyperstart], [0.1], [www.hyper.sh])
|
AC_INIT([hyperstart], [0.3], [www.hyper.sh])
|
||||||
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
AM_INIT_AUTOMAKE([-Wall -Werror foreign subdir-objects])
|
||||||
AM_EXTRA_RECURSIVE_TARGETS([cbfs])
|
AM_EXTRA_RECURSIVE_TARGETS([initrd cbfs])
|
||||||
AC_CONFIG_SRCDIR([src/init.c])
|
AC_CONFIG_SRCDIR([src/init.c])
|
||||||
AC_CONFIG_HEADERS([config.h])
|
AC_CONFIG_HEADERS([config.h])
|
||||||
|
|
||||||
@@ -32,20 +32,22 @@ AC_TYPE_UINT8_T
|
|||||||
# Checks for library functions.
|
# Checks for library functions.
|
||||||
AC_FUNC_FORK
|
AC_FUNC_FORK
|
||||||
AC_CHECK_FUNCS([dup2 memmove memset mkdir setenv socket strchr strdup strrchr strtoul], [fail=0], [fail=1])
|
AC_CHECK_FUNCS([dup2 memmove memset mkdir setenv socket strchr strdup strrchr strtoul], [fail=0], [fail=1])
|
||||||
|
AC_CHECK_FUNCS([setns])
|
||||||
|
|
||||||
if test "$fail" = "1" ; then
|
if test "$fail" = "1" ; then
|
||||||
AC_MSG_ERROR(Unable to find necessary functions)
|
AC_MSG_ERROR(Unable to find necessary functions)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
AC_ARG_WITH([ttys],
|
AC_ARG_WITH([vbox],
|
||||||
[AS_HELP_STRING([--with-ttys],
|
[AS_HELP_STRING([--with-vbox],
|
||||||
[use pci serial device as container tty])],
|
[run hyperstart on Virtualbox])],
|
||||||
[],[with_ttys=yes])
|
[],[with_vbox=no])
|
||||||
|
|
||||||
if test "x$with_ttys" != "xno" ; then
|
if test "x$with_vbox" != "xno" ; then
|
||||||
AC_DEFINE_UNQUOTED([WITH_TTYS], 1, [where use pci serial device as container tty])
|
AC_DEFINE_UNQUOTED([WITH_VBOX], 1, [run hyperstart on Virtualbox])
|
||||||
fi
|
fi
|
||||||
AM_CONDITIONAL([WITH_TTYS], [test "x$with_ttys" != "xno"])
|
|
||||||
|
AM_CONDITIONAL([WITH_VBOX], [test "x$with_vbox" != "xno"])
|
||||||
|
|
||||||
AC_CONFIG_FILES([
|
AC_CONFIG_FILES([
|
||||||
Makefile
|
Makefile
|
||||||
@@ -58,7 +60,7 @@ AC_MSG_RESULT([
|
|||||||
${PACKAGE} ${VERSION}
|
${PACKAGE} ${VERSION}
|
||||||
prefix: ${prefix}
|
prefix: ${prefix}
|
||||||
|
|
||||||
with-ttys: ${with_ttys}
|
with-vbox: ${with_vbox}
|
||||||
|
|
||||||
compiler: ${CC}
|
compiler: ${CC}
|
||||||
cflags: ${CFLAGS}
|
cflags: ${CFLAGS}
|
||||||
|
|||||||
+226
-137
@@ -16,20 +16,8 @@
|
|||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
|
#include "parse.h"
|
||||||
static int container_setup_env(struct hyper_container *container)
|
#include "syscall.h"
|
||||||
{
|
|
||||||
int i;
|
|
||||||
struct env *env;
|
|
||||||
|
|
||||||
for (i = 0; i < container->envs_num; i++) {
|
|
||||||
env = &container->envs[i];
|
|
||||||
|
|
||||||
setenv(env->env, env->value, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int container_setup_volume(struct hyper_container *container)
|
static int container_setup_volume(struct hyper_container *container)
|
||||||
{
|
{
|
||||||
@@ -40,29 +28,34 @@ static int container_setup_volume(struct hyper_container *container)
|
|||||||
for (i = 0; i < container->vols_num; i++) {
|
for (i = 0; i < container->vols_num; i++) {
|
||||||
vol = &container->vols[i];
|
vol = &container->vols[i];
|
||||||
|
|
||||||
|
if (vol->scsiaddr)
|
||||||
|
hyper_find_sd("/.oldroot", vol->scsiaddr, &vol->device);
|
||||||
|
|
||||||
sprintf(dev, "/.oldroot/dev/%s", vol->device);
|
sprintf(dev, "/.oldroot/dev/%s", vol->device);
|
||||||
sprintf(path, "/tmp/%s", vol->mountpoint);
|
sprintf(path, "/tmp/%s", vol->mountpoint);
|
||||||
fprintf(stdout, "mount %s to %s\n", dev, vol->mountpoint);
|
fprintf(stdout, "mount %s to %s, tmp path %s\n",
|
||||||
|
dev, vol->mountpoint, path);
|
||||||
|
|
||||||
if (hyper_mkdir(path) < 0 || hyper_mkdir(vol->mountpoint) < 0) {
|
if (hyper_mkdir(path) < 0 || hyper_mkdir(vol->mountpoint) < 0) {
|
||||||
fprintf(stdout, "mountpoint %s\n", vol->mountpoint);
|
|
||||||
perror("create volume dir failed");
|
perror("create volume dir failed");
|
||||||
continue;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount(dev, path, vol->fstype, 0, NULL) < 0) {
|
if (mount(dev, path, vol->fstype, 0, NULL) < 0) {
|
||||||
perror("mount volume device faled");
|
perror("mount volume device faled");
|
||||||
continue;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) {
|
if (mount(path, vol->mountpoint, NULL, MS_BIND, NULL) < 0) {
|
||||||
perror("mount volume device faled");
|
perror("mount volume device faled");
|
||||||
continue;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vol->readonly &&
|
if (vol->readonly &&
|
||||||
mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0)
|
mount(path, vol->mountpoint, NULL, MS_BIND | MS_REMOUNT | MS_RDONLY, NULL) < 0) {
|
||||||
perror("mount fsmap faled");
|
perror("mount fsmap faled");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
umount(path);
|
umount(path);
|
||||||
}
|
}
|
||||||
@@ -110,13 +103,27 @@ static int container_setup_mount(struct hyper_container *container)
|
|||||||
char src[512];
|
char src[512];
|
||||||
struct fsmap *map;
|
struct fsmap *map;
|
||||||
|
|
||||||
if (mount("proc", "/proc", "proc", 0, NULL) < 0 ||
|
hyper_mkdir("/proc");
|
||||||
mount("sysfs", "/sys", "sysfs", 0, NULL) < 0 ||
|
hyper_mkdir("/sys");
|
||||||
mount("devtmpfs", "/dev", "devtmpfs", 0, NULL) < 0) {
|
hyper_mkdir("/dev");
|
||||||
|
|
||||||
|
if (mount("proc", "/proc", "proc", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
|
||||||
|
mount("sysfs", "/sys", "sysfs", MS_NOSUID| MS_NODEV| MS_NOEXEC, NULL) < 0 ||
|
||||||
|
mount("devtmpfs", "/dev", "devtmpfs", MS_NOSUID, NULL) < 0) {
|
||||||
perror("mount basic filesystem for container failed");
|
perror("mount basic filesystem for container failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hyper_mkdir("/dev/shm") < 0) {
|
||||||
|
fprintf(stderr, "create /dev/shm failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mount("tmpfs", "/dev/shm/", "tmpfs", MS_NOSUID| MS_NODEV, NULL) < 0) {
|
||||||
|
perror("mount shm failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
if (hyper_mkdir("/dev/pts") < 0) {
|
if (hyper_mkdir("/dev/pts") < 0) {
|
||||||
fprintf(stderr, "create /dev/pts failed\n");
|
fprintf(stderr, "create /dev/pts failed\n");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -175,6 +182,78 @@ static int container_setup_mount(struct hyper_container *container)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int container_setup_sysctl(struct hyper_container *container)
|
||||||
|
{
|
||||||
|
int i, size, len, l, fd;
|
||||||
|
struct sysctl *sys;
|
||||||
|
|
||||||
|
for (i = 0; i < container->sys_num; i++) {
|
||||||
|
char path[256];
|
||||||
|
|
||||||
|
len = 0;
|
||||||
|
sys = &container->sys[i];
|
||||||
|
size = strlen(sys->value);
|
||||||
|
|
||||||
|
sprintf(path, "/proc/sys/%s", sys->path);
|
||||||
|
fprintf(stdout, "sysctl %s value %s\n", sys->path, sys->value);
|
||||||
|
|
||||||
|
fd = open(path, O_WRONLY);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("open file failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (len < size) {
|
||||||
|
l = write(fd, sys->value + len, size - len);
|
||||||
|
if (l < 0) {
|
||||||
|
perror("fail to write sysctl");
|
||||||
|
close(fd);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
len += l;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
out:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int container_setup_dns(struct hyper_container *container)
|
||||||
|
{
|
||||||
|
int fd;
|
||||||
|
struct stat st;
|
||||||
|
char *src = "/.oldroot/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");
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
static int container_setup_workdir(struct hyper_container *container)
|
static int container_setup_workdir(struct hyper_container *container)
|
||||||
{
|
{
|
||||||
if (container->workdir && chdir(container->workdir) < 0) {
|
if (container->workdir && chdir(container->workdir) < 0) {
|
||||||
@@ -237,6 +316,8 @@ static int hyper_rescan_scsi(void)
|
|||||||
|
|
||||||
struct hyper_container_arg {
|
struct hyper_container_arg {
|
||||||
struct hyper_container *c;
|
struct hyper_container *c;
|
||||||
|
int ipcns;
|
||||||
|
int utsns;
|
||||||
int pipe[2];
|
int pipe[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -252,12 +333,22 @@ static int hyper_container_init(void *data)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (setns(arg->ipcns, CLONE_NEWIPC) < 0) {
|
||||||
|
perror("setns to ipcns of pod init faild");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setns(arg->utsns, CLONE_NEWUTS) < 0) {
|
||||||
|
perror("setns to ipcns of pod init faild");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
if (hyper_rescan_scsi() < 0) {
|
if (hyper_rescan_scsi() < 0) {
|
||||||
fprintf(stdout, "rescan scsi failed\n");
|
fprintf(stdout, "rescan scsi failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (container_setup_env(container) < 0) {
|
if (hyper_setup_env(container->envs, container->envs_num) < 0) {
|
||||||
fprintf(stdout, "setup env failed\n");
|
fprintf(stdout, "setup env failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
@@ -283,6 +374,9 @@ static int hyper_container_init(void *data)
|
|||||||
if (container->fstype) {
|
if (container->fstype) {
|
||||||
char dev[128];
|
char dev[128];
|
||||||
|
|
||||||
|
if (container->scsiaddr)
|
||||||
|
hyper_find_sd("", container->scsiaddr, &container->image);
|
||||||
|
|
||||||
sprintf(dev, "/dev/%s", container->image);
|
sprintf(dev, "/dev/%s", container->image);
|
||||||
fprintf(stdout, "device %s\n", dev);
|
fprintf(stdout, "device %s\n", dev);
|
||||||
|
|
||||||
@@ -305,7 +399,6 @@ static int hyper_container_init(void *data)
|
|||||||
fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
|
fprintf(stdout, "root directory for container is %s/%s, init task %s\n",
|
||||||
root, container->rootfs, container->exec.argv[0]);
|
root, container->rootfs, container->exec.argv[0]);
|
||||||
|
|
||||||
hyper_list_dir(root);
|
|
||||||
sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs);
|
sprintf(oldroot, "%s/%s/.oldroot", root, container->rootfs);
|
||||||
if (hyper_mkdir(oldroot) < 0) {
|
if (hyper_mkdir(oldroot) < 0) {
|
||||||
perror("make oldroot directroy failed");
|
perror("make oldroot directroy failed");
|
||||||
@@ -330,7 +423,17 @@ static int hyper_container_init(void *data)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (container_setup_mount(container) < 0) {
|
if (container_setup_mount(container) < 0) {
|
||||||
fprintf(stderr, "container sets up mount ns failed\n");
|
fprintf(stderr, "container sets up mount failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container_setup_sysctl(container) < 0) {
|
||||||
|
fprintf(stderr, "container sets up sysctl failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container_setup_dns(container) < 0) {
|
||||||
|
fprintf(stderr, "container sets up dns failed\n");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -348,28 +451,60 @@ static int hyper_container_init(void *data)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(arg->pipe[0]);
|
symlink("/proc/self/fd", "/dev/fd");
|
||||||
close(arg->pipe[1]);
|
symlink("/proc/self/fd/0", "/dev/stdin");
|
||||||
|
symlink("/proc/self/fd/1", "/dev/stdout");
|
||||||
|
symlink("/proc/self/fd/2", "/dev/stderr");
|
||||||
|
|
||||||
execvp(container->exec.argv[0], container->exec.argv);
|
execvp(container->exec.argv[0], container->exec.argv);
|
||||||
|
perror("exec container command failed");
|
||||||
|
|
||||||
_exit(-1);
|
_exit(-1);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
container->exec.code = -1;
|
hyper_send_type(arg->pipe[1], ERROR);
|
||||||
hyper_send_type_block(arg->pipe[1], ERROR, 0);
|
|
||||||
_exit(-1);
|
_exit(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_start_container(struct hyper_container *container)
|
static int hyper_setup_pty(struct hyper_container *c)
|
||||||
|
{
|
||||||
|
char root[512];
|
||||||
|
|
||||||
|
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||||
|
|
||||||
|
if (hyper_mkdir(root) < 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_setup_exec_tty(&c->exec) < 0) {
|
||||||
|
fprintf(stderr, "setup container pts failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hyper_start_container(struct hyper_container *container,
|
||||||
|
int utsns, int ipcns, struct hyper_pod *pod)
|
||||||
{
|
{
|
||||||
int stacksize = getpagesize() * 4;
|
int stacksize = getpagesize() * 4;
|
||||||
void *stack = malloc(stacksize);
|
|
||||||
struct hyper_container_arg arg = {
|
struct hyper_container_arg arg = {
|
||||||
.c = container,
|
.c = container,
|
||||||
|
.utsns = utsns,
|
||||||
|
.ipcns = ipcns,
|
||||||
|
.pipe = {-1, -1},
|
||||||
};
|
};
|
||||||
int flags = CLONE_NEWNS | SIGCHLD;
|
int flags = CLONE_NEWNS | SIGCHLD;
|
||||||
|
char path[128];
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
|
void *stack;
|
||||||
int pid;
|
int pid;
|
||||||
|
|
||||||
if (container->image == NULL || container->exec.argv == NULL) {
|
if (container->image == NULL || container->exec.argv == NULL) {
|
||||||
@@ -378,151 +513,105 @@ int hyper_start_container(struct hyper_container *container)
|
|||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (socketpair(PF_UNIX, SOCK_STREAM, 0, arg.pipe) < 0) {
|
if (hyper_setup_pty(container) < 0) {
|
||||||
|
fprintf(stderr, "setup pty device for container failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipe2(arg.pipe, O_CLOEXEC) < 0) {
|
||||||
perror("create pipe between pod init execcmd failed");
|
perror("create pipe between pod init execcmd failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (hyper_watch_exec_pty(&container->exec, pod) < 0) {
|
||||||
|
fprintf(stderr, "faile to watch container pty\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
stack = malloc(stacksize);
|
||||||
|
if (stack == NULL) {
|
||||||
|
perror("fail to allocate stack for container init");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
pid = clone(hyper_container_init, stack + stacksize, flags, &arg);
|
pid = clone(hyper_container_init, stack + stacksize, flags, &arg);
|
||||||
free(stack);
|
free(stack);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
perror("create child process failed");
|
perror("create child process failed");
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
sprintf(path, "/proc/%d/ns/mnt", pid);
|
||||||
|
|
||||||
container->exec.pid = pid;
|
container->ns = open(path, O_RDONLY | O_CLOEXEC);
|
||||||
|
if (container->ns < 0) {
|
||||||
/* wait for ready message */
|
perror("open container mount ns failed");
|
||||||
if (hyper_get_type_block(arg.pipe[0], &type) < 0 || type != READY) {
|
|
||||||
fprintf(stdout, "wait for container started failed\n");
|
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wait for ready message */
|
||||||
|
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
|
||||||
|
fprintf(stderr, "wait for container started failed\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
container->exec.pid = pid;
|
||||||
|
list_add_tail(&container->exec.list, &pod->exec_head);
|
||||||
|
container->exec.ref++;
|
||||||
|
|
||||||
close(arg.pipe[0]);
|
close(arg.pipe[0]);
|
||||||
close(arg.pipe[1]);
|
close(arg.pipe[1]);
|
||||||
|
|
||||||
fprintf(stdout, "container %s init pid is %d\n", container->id, pid);
|
fprintf(stdout, "container %s,init pid %d,ref %d\n", container->id, pid, container->exec.ref);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
|
close(arg.pipe[0]);
|
||||||
|
close(arg.pipe[1]);
|
||||||
|
close(container->ns);
|
||||||
|
hyper_reset_event(&container->exec.e);
|
||||||
|
hyper_reset_event(&container->exec.errev);
|
||||||
|
container->ns = -1;
|
||||||
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
|
fprintf(stdout, "container %s init exit code %d\n", container->id, -1);
|
||||||
container->exec.code = -1;
|
container->exec.code = -1;
|
||||||
|
container->exec.seq = 0;
|
||||||
|
container->exec.ref = 0;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_start_containers(struct hyper_pod *pod)
|
|
||||||
{
|
|
||||||
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)
|
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id)
|
||||||
{
|
{
|
||||||
int i;
|
struct hyper_container *c;
|
||||||
struct hyper_container *container;
|
|
||||||
|
|
||||||
for (i = 0; i < pod->c_num; i++) {
|
list_for_each_entry(c, &pod->containers, list) {
|
||||||
container = &pod->c[i];
|
if (strlen(c->id) != strlen(id))
|
||||||
|
|
||||||
if (strlen(container->id) != strlen(id))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (strncmp(container->id, id, strlen(id)))
|
if (strncmp(c->id, id, strlen(id)))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
return container;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyper_cleanup_container(struct hyper_pod *pod)
|
void hyper_cleanup_container(struct hyper_container *c)
|
||||||
{
|
{
|
||||||
int i, j;
|
|
||||||
struct hyper_container *c;
|
|
||||||
struct volume *vol;
|
|
||||||
struct env *env;
|
|
||||||
struct fsmap *map;
|
|
||||||
char root[512];
|
char root[512];
|
||||||
|
|
||||||
for (i = 0; i < pod->c_num; i++) {
|
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
||||||
c = &pod->c[i];
|
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
||||||
|
perror("umount devpts failed");
|
||||||
|
|
||||||
sprintf(root, "/tmp/hyper/%s/devpts/", c->id);
|
close(c->ns);
|
||||||
if (umount(root) < 0 && umount2(root, MNT_DETACH))
|
hyper_free_container(c);
|
||||||
perror("umount devpts failed");
|
}
|
||||||
|
|
||||||
free(c->id);
|
void hyper_cleanup_containers(struct hyper_pod *pod)
|
||||||
free(c->rootfs);
|
{
|
||||||
free(c->image);
|
struct hyper_container *c, *n;
|
||||||
free(c->workdir);
|
|
||||||
free(c->fstype);
|
|
||||||
|
|
||||||
for (j = 0; j < c->vols_num; j++) {
|
list_for_each_entry_safe(c, n, &pod->containers, list)
|
||||||
vol = &(c->vols[j]);
|
hyper_cleanup_container(c);
|
||||||
free(vol->device);
|
|
||||||
free(vol->mountpoint);
|
|
||||||
free(vol->fstype);
|
|
||||||
}
|
|
||||||
free(c->vols);
|
|
||||||
|
|
||||||
for (j = 0; j < c->envs_num; j++) {
|
pod->remains = 0;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+16
-3
@@ -10,6 +10,7 @@ struct env {
|
|||||||
|
|
||||||
struct volume {
|
struct volume {
|
||||||
char *device;
|
char *device;
|
||||||
|
char *scsiaddr;
|
||||||
char *mountpoint;
|
char *mountpoint;
|
||||||
char *fstype;
|
char *fstype;
|
||||||
int readonly;
|
int readonly;
|
||||||
@@ -21,27 +22,39 @@ struct fsmap {
|
|||||||
int readonly;
|
int readonly;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct sysctl {
|
||||||
|
char *path;
|
||||||
|
char *value;
|
||||||
|
};
|
||||||
|
|
||||||
struct hyper_container {
|
struct hyper_container {
|
||||||
char *id;
|
char *id;
|
||||||
char *rootfs;
|
char *rootfs;
|
||||||
char *image;
|
char *image;
|
||||||
|
char *scsiaddr;
|
||||||
char *workdir;
|
char *workdir;
|
||||||
char *fstype;
|
char *fstype;
|
||||||
struct volume *vols;
|
struct volume *vols;
|
||||||
struct env *envs;
|
struct env *envs;
|
||||||
struct fsmap *maps;
|
struct fsmap *maps;
|
||||||
|
struct sysctl *sys;
|
||||||
int vols_num;
|
int vols_num;
|
||||||
int envs_num;
|
int envs_num;
|
||||||
int maps_num;
|
int maps_num;
|
||||||
|
int sys_num;
|
||||||
|
int ns;
|
||||||
uint32_t code;
|
uint32_t code;
|
||||||
|
struct list_head list;
|
||||||
struct hyper_exec exec;
|
struct hyper_exec exec;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_pod;
|
struct hyper_pod;
|
||||||
|
|
||||||
int hyper_start_containers(struct hyper_pod *pod);
|
int hyper_start_container(struct hyper_container *container,
|
||||||
|
int utsns, int ipcns, struct hyper_pod *pod);
|
||||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
||||||
int hyper_restart_containers(struct hyper_pod *pod);
|
void hyper_cleanup_container(struct hyper_container *container);
|
||||||
void hyper_cleanup_container(struct hyper_pod *pod);
|
void hyper_cleanup_containers(struct hyper_pod *pod);
|
||||||
|
void hyper_free_container(struct hyper_container *c);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+190
-22
@@ -5,33 +5,45 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "net.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "hyper.h"
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
|
|
||||||
void hyper_reset_event(struct hyper_event *de)
|
void hyper_reset_event(struct hyper_event *de)
|
||||||
{
|
{
|
||||||
free(de->buf.data);
|
free(de->rbuf.data);
|
||||||
de->buf.data = NULL;
|
free(de->wbuf.data);
|
||||||
|
close(de->fd);
|
||||||
memset(de, 0, sizeof(*de));
|
memset(de, 0, sizeof(*de));
|
||||||
|
de->fd = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_init_event(struct hyper_event *de,
|
int hyper_init_event(struct hyper_event *de, struct hyper_event_ops *ops, void *arg)
|
||||||
struct hyper_event_ops *ops,
|
|
||||||
uint32_t size, int to, void *arg)
|
|
||||||
{
|
{
|
||||||
struct hyper_buf *buf = &de->buf;
|
struct hyper_buf *rbuf = &de->rbuf;
|
||||||
|
struct hyper_buf *wbuf = &de->wbuf;
|
||||||
|
|
||||||
memset(buf, 0, sizeof(*buf));
|
memset(rbuf, 0, sizeof(*rbuf));
|
||||||
|
memset(wbuf, 0, sizeof(*wbuf));
|
||||||
|
|
||||||
de->ops = ops;
|
de->ops = ops;
|
||||||
de->ptr = arg;
|
de->ptr = arg;
|
||||||
de->to = to;
|
rbuf->size = ops->rbuf_size;
|
||||||
buf->size = size;
|
wbuf->size = ops->wbuf_size;
|
||||||
|
|
||||||
if (size) {
|
if (rbuf->size) {
|
||||||
buf->data = malloc(size);
|
rbuf->data = malloc(rbuf->size);
|
||||||
if (buf->data == NULL) {
|
if (rbuf->data == NULL) {
|
||||||
fprintf(stderr, "allocate data for event failed\n");
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,13 +51,14 @@ int hyper_init_event(struct hyper_event *de,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_add_event(int efd, struct hyper_event *de)
|
int hyper_add_event(int efd, struct hyper_event *de, int flag)
|
||||||
{
|
{
|
||||||
struct epoll_event event = {
|
struct epoll_event event = {
|
||||||
.events = EPOLLIN,
|
.events = flag,
|
||||||
.data.ptr = de,
|
.data.ptr = de,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
de->flag = flag;
|
||||||
if (hyper_setfd_nonblock(de->fd) < 0) {
|
if (hyper_setfd_nonblock(de->fd) < 0) {
|
||||||
perror("set fd nonblock failed");
|
perror("set fd nonblock failed");
|
||||||
return -1;
|
return -1;
|
||||||
@@ -61,31 +74,186 @@ int hyper_add_event(int efd, struct hyper_event *de)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hyper_modify_event(int efd, struct hyper_event *de, int flag)
|
||||||
|
{
|
||||||
|
struct epoll_event event = {
|
||||||
|
.events = flag,
|
||||||
|
.data.ptr = de,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (de->flag == flag)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
de->flag = flag;
|
||||||
|
fprintf(stdout, "%s modify event fd %d, %p, event %d\n",
|
||||||
|
__func__, de->fd, de, flag);
|
||||||
|
|
||||||
|
if (epoll_ctl(efd, EPOLL_CTL_MOD, de->fd, &event) < 0) {
|
||||||
|
perror("epoll_ctl fd failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int hyper_getmsg_len(struct hyper_event *de, uint32_t *len)
|
||||||
|
{
|
||||||
|
struct hyper_buf *buf = &de->rbuf;
|
||||||
|
|
||||||
|
if (buf->get < de->ops->len_offset + 4)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
*len = hyper_get_be32(buf->data + de->ops->len_offset);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hyper_event_read(struct hyper_event *de)
|
||||||
|
{
|
||||||
|
struct hyper_buf *buf = &de->rbuf;
|
||||||
|
uint32_t len = 4;
|
||||||
|
uint8_t data[4];
|
||||||
|
int offset = de->ops->len_offset;
|
||||||
|
int end = offset + 4;
|
||||||
|
int size;
|
||||||
|
|
||||||
|
fprintf(stdout, "%s\n", __func__);
|
||||||
|
|
||||||
|
while (hyper_getmsg_len(de, &len) < 0) {
|
||||||
|
size = read(de->fd, buf->data + buf->get, end - buf->get);
|
||||||
|
if (size > 0) {
|
||||||
|
buf->get += size;
|
||||||
|
fprintf(stdout, "already read %" PRIu32 " bytes data\n",
|
||||||
|
buf->get);
|
||||||
|
|
||||||
|
if (de->ops->ack) {
|
||||||
|
/* control channel, need ack */
|
||||||
|
hyper_set_be32(data, size);
|
||||||
|
hyper_send_msg(de->fd, NEXT, 4, data);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (errno != EAGAIN && size != 0) {
|
||||||
|
perror("fail to read");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 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(de->fd, buf->data + buf->get, len - buf->get);
|
||||||
|
if (size > 0) {
|
||||||
|
buf->get += size;
|
||||||
|
fprintf(stdout, "read %d bytes data, total data %" PRIu32 "\n",
|
||||||
|
size, buf->get);
|
||||||
|
if (de->ops->ack) {
|
||||||
|
/* control channel, need ack */
|
||||||
|
hyper_set_be32(data, size);
|
||||||
|
hyper_send_msg(de->fd, NEXT, 4, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (errno == EINTR)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (errno != EAGAIN && size != 0) {
|
||||||
|
perror("fail to read");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* size == 0 : No one connect to qemu socket */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get the whole data */
|
||||||
|
if (de->ops->handle(de, len) != 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
/* len: length of the already get new data */
|
||||||
|
buf->get -= len;
|
||||||
|
memmove(buf->data, buf->data + len, buf->get);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hyper_event_write(struct hyper_event *de)
|
||||||
|
{
|
||||||
|
struct hyper_buf *buf = &de->wbuf;
|
||||||
|
uint32_t len = 0;
|
||||||
|
int size = 0;
|
||||||
|
|
||||||
|
while (len < buf->get) {
|
||||||
|
size = write(de->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, de, EPOLLIN);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
void hyper_event_hup(struct hyper_event *de, int efd)
|
void hyper_event_hup(struct hyper_event *de, int efd)
|
||||||
{
|
{
|
||||||
if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0)
|
if (epoll_ctl(efd, EPOLL_CTL_DEL, de->fd, NULL) < 0)
|
||||||
perror("epoll_ctl del epoll event failed");
|
perror("epoll_ctl del epoll event failed");
|
||||||
close(de->fd);
|
|
||||||
hyper_reset_event(de);
|
hyper_reset_event(de);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_handle_event(int efd, struct epoll_event *event)
|
int hyper_handle_event(int efd, struct epoll_event *event)
|
||||||
{
|
{
|
||||||
struct hyper_event *de = event->data.ptr;
|
struct hyper_event *de = event->data.ptr;
|
||||||
|
fprintf(stdout, "%s get event %d, de %p, fd %d. ops %p\n",
|
||||||
|
__func__, event->events, de, de->fd, de->ops);
|
||||||
|
|
||||||
if (event->events & EPOLLHUP) {
|
/* do not handle hup event if have in event */
|
||||||
|
if (event->events & EPOLLIN) {
|
||||||
|
fprintf(stdout, "%s event EPOLLIN, de %p, fd %d, %p\n",
|
||||||
|
__func__, de, de->fd, de->ops);
|
||||||
|
if (de->ops->read(de) < 0)
|
||||||
|
return -1;
|
||||||
|
} else if (event->events & EPOLLHUP) {
|
||||||
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
|
fprintf(stdout, "%s event EPOLLHUP, de %p, fd %d, %p\n",
|
||||||
__func__, de, de->fd, de->ops);
|
__func__, de, de->fd, de->ops);
|
||||||
if (de->ops->hup)
|
if (de->ops->hup)
|
||||||
de->ops->hup(de, efd);
|
de->ops->hup(de, efd);
|
||||||
return 0;
|
return 0;
|
||||||
} else if (event->events & EPOLLIN) {
|
}
|
||||||
return de->ops->read(de);
|
|
||||||
} else if (event->events & EPOLLERR) {
|
if (event->events & EPOLLOUT) {
|
||||||
|
fprintf(stdout, "%s event EPOLLOUT, de %p, fd %d, %p\n",
|
||||||
|
__func__, de, de->fd, de->ops);
|
||||||
|
if (de->ops->write && de->ops->write(de) < 0)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event->events & EPOLLERR) {
|
||||||
fprintf(stderr, "get epoll err of not epool in event\n");
|
fprintf(stderr, "get epoll err of not epool in event\n");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "%s get unknown event %d\n", __func__, event->events);
|
return 0;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-5
@@ -8,9 +8,13 @@ struct hyper_event;
|
|||||||
|
|
||||||
struct hyper_event_ops {
|
struct hyper_event_ops {
|
||||||
int (*read)(struct hyper_event *e);
|
int (*read)(struct hyper_event *e);
|
||||||
int (*getlen)(struct hyper_event *e, uint32_t *len);
|
int (*write)(struct hyper_event *e);
|
||||||
int (*handle)(struct hyper_event *e, uint32_t len);
|
int (*handle)(struct hyper_event *e, uint32_t len);
|
||||||
void (*hup)(struct hyper_event *e, int efd);
|
void (*hup)(struct hyper_event *e, int efd);
|
||||||
|
int rbuf_size;
|
||||||
|
int wbuf_size;
|
||||||
|
int len_offset;
|
||||||
|
int ack;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_buf {
|
struct hyper_buf {
|
||||||
@@ -21,16 +25,20 @@ struct hyper_buf {
|
|||||||
|
|
||||||
struct hyper_event {
|
struct hyper_event {
|
||||||
int fd;
|
int fd;
|
||||||
int to;
|
int flag;
|
||||||
struct hyper_buf buf;
|
struct hyper_buf rbuf;
|
||||||
|
struct hyper_buf wbuf;
|
||||||
struct hyper_event_ops *ops;
|
struct hyper_event_ops *ops;
|
||||||
void *ptr;
|
void *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
int hyper_add_event(int efd, struct hyper_event *de);
|
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_init_event(struct hyper_event *de, struct hyper_event_ops *ops,
|
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);
|
int hyper_handle_event(int efd, struct epoll_event *event);
|
||||||
void hyper_reset_event(struct hyper_event *de);
|
void hyper_reset_event(struct hyper_event *de);
|
||||||
void hyper_event_hup(struct hyper_event *de, int efd);
|
void hyper_event_hup(struct hyper_event *de, int efd);
|
||||||
|
int hyper_event_read(struct hyper_event *de);
|
||||||
|
int hyper_event_write(struct hyper_event *de);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+408
-300
@@ -9,49 +9,123 @@
|
|||||||
#include <sched.h>
|
#include <sched.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
#include "syscall.h"
|
|
||||||
|
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "parse.h"
|
#include "parse.h"
|
||||||
|
#include "syscall.h"
|
||||||
|
|
||||||
static int pts_loop(struct hyper_event *de)
|
static void pts_hup(struct hyper_event *de, int efd, int out)
|
||||||
{
|
{
|
||||||
int size = 0;
|
struct hyper_exec *exec;
|
||||||
uint8_t buf[512];
|
struct hyper_pod *pod = de->ptr;
|
||||||
uint8_t seq[12];
|
struct hyper_buf *buf = &ctl.tty.wbuf;
|
||||||
struct hyper_exec *exec = container_of(de, struct hyper_exec, e);
|
uint64_t seq;
|
||||||
|
|
||||||
|
if (out) {
|
||||||
|
exec = container_of(de, struct hyper_exec, e);
|
||||||
|
seq = exec->seq;
|
||||||
|
} else {
|
||||||
|
exec = container_of(de, struct hyper_exec, errev);
|
||||||
|
seq = exec->errseq;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, seq);
|
||||||
|
|
||||||
|
hyper_event_hup(de, efd);
|
||||||
|
|
||||||
|
if (buf->get + 12 > buf->size) {
|
||||||
|
fprintf(stdout, "%s: tty buf full\n", __func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no in event, no more data, send eof */
|
||||||
|
hyper_set_be64(buf->data + buf->get, seq);
|
||||||
|
hyper_set_be32(buf->data + buf->get + 8, 12);
|
||||||
|
buf->get += 12;
|
||||||
|
|
||||||
|
hyper_modify_event(ctl.efd, &ctl.tty, EPOLLIN | EPOLLOUT);
|
||||||
|
|
||||||
|
hyper_release_exec(exec, pod);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void stdout_hup(struct hyper_event *de, int efd)
|
||||||
|
{
|
||||||
fprintf(stdout, "%s\n", __func__);
|
fprintf(stdout, "%s\n", __func__);
|
||||||
while (1) {
|
return pts_hup(de, efd, 1);
|
||||||
size = read(de->fd, buf, sizeof(buf));
|
}
|
||||||
|
|
||||||
|
static void stderr_hup(struct hyper_event *de, int efd)
|
||||||
|
{
|
||||||
|
fprintf(stdout, "%s\n", __func__);
|
||||||
|
return pts_hup(de, efd, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int pts_loop(struct hyper_event *de, uint64_t seq)
|
||||||
|
{
|
||||||
|
int size = -1;
|
||||||
|
struct hyper_buf *buf = &ctl.tty.wbuf;
|
||||||
|
|
||||||
|
while ((buf->get + 12 < buf->size) && size) {
|
||||||
|
size = read(de->fd, buf->data + buf->get + 12, buf->size - buf->get - 12);
|
||||||
|
fprintf(stdout, "%s: read %d data\n", __func__, size);
|
||||||
if (size <= 0) {
|
if (size <= 0) {
|
||||||
if (errno == EINTR)
|
if (errno == EINTR)
|
||||||
continue;
|
continue;
|
||||||
if (errno == EAGAIN || errno == EIO)
|
|
||||||
break;
|
|
||||||
|
|
||||||
perror("fail to read tty fd");
|
if (errno != EAGAIN && errno != EIO) {
|
||||||
return -1;
|
perror("fail to read tty fd");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
hyper_set_be64(seq, exec->seq);
|
hyper_set_be64(buf->data + buf->get, seq);
|
||||||
hyper_set_be32(seq + 8, size + 12);
|
hyper_set_be32(buf->data + buf->get + 8, size + 12);
|
||||||
|
buf->get += size + 12;
|
||||||
|
}
|
||||||
|
|
||||||
if (hyper_send_data(de->to, seq, 12) < 0)
|
if (hyper_modify_event(ctl.efd, &ctl.tty, EPOLLIN | EPOLLOUT) < 0) {
|
||||||
continue;
|
fprintf(stderr, "modify ctl tty event to in & out failed\n");
|
||||||
|
return -1;
|
||||||
hyper_send_data(de->to, buf, size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int stdout_loop(struct hyper_event *de)
|
||||||
|
{
|
||||||
|
struct hyper_exec *exec = container_of(de, struct hyper_exec, e);
|
||||||
|
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->seq);
|
||||||
|
|
||||||
|
return pts_loop(de, exec->seq);
|
||||||
|
}
|
||||||
|
|
||||||
struct hyper_event_ops pts_ops = {
|
struct hyper_event_ops pts_ops = {
|
||||||
.read = pts_loop,
|
.read = stdout_loop,
|
||||||
.hup = hyper_event_hup,
|
.hup = stdout_hup,
|
||||||
|
.write = hyper_event_write,
|
||||||
|
.wbuf_size = 512,
|
||||||
|
/* don't need read buff, the pts data will store in tty buffer */
|
||||||
|
};
|
||||||
|
|
||||||
|
static int stderr_loop(struct hyper_event *de)
|
||||||
|
{
|
||||||
|
struct hyper_exec *exec = container_of(de, struct hyper_exec, errev);
|
||||||
|
fprintf(stdout, "%s, seq %" PRIu64"\n", __func__, exec->errseq);
|
||||||
|
|
||||||
|
return pts_loop(de, exec->errseq);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hyper_event_ops err_ops = {
|
||||||
|
.read = stderr_loop,
|
||||||
|
.hup = stderr_hup,
|
||||||
|
/* don't need read buff, the stderr data will store in tty buffer */
|
||||||
|
/* don't need write buff, the stderr data is one way */
|
||||||
};
|
};
|
||||||
|
|
||||||
int hyper_setup_exec_tty(struct hyper_exec *e)
|
int hyper_setup_exec_tty(struct hyper_exec *e)
|
||||||
@@ -62,6 +136,16 @@ int hyper_setup_exec_tty(struct hyper_exec *e)
|
|||||||
if (e->seq == 0)
|
if (e->seq == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (e->errseq > 0) {
|
||||||
|
int errpipe[2];
|
||||||
|
if (pipe2(errpipe, O_NONBLOCK|O_CLOEXEC) < 0) {
|
||||||
|
fprintf(stderr, "creating stderr pipe failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
e->errev.fd = errpipe[0];
|
||||||
|
e->errfd = errpipe[1];
|
||||||
|
}
|
||||||
|
|
||||||
if (e->id) {
|
if (e->id) {
|
||||||
if (sprintf(path, "/tmp/hyper/%s/devpts/", e->id) < 0) {
|
if (sprintf(path, "/tmp/hyper/%s/devpts/", e->id) < 0) {
|
||||||
fprintf(stderr, "get ptmx path failed\n");
|
fprintf(stderr, "get ptmx path failed\n");
|
||||||
@@ -100,334 +184,382 @@ int hyper_setup_exec_tty(struct hyper_exec *e)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
e->pty = strdup(ptmx);
|
e->ptyfd = open(ptmx, O_RDWR | O_NOCTTY | O_CLOEXEC);
|
||||||
fprintf(stdout, "get pty device for exec %s\n", e->pty);
|
fprintf(stdout, "get pty device for exec %s\n", ptmx);
|
||||||
|
|
||||||
|
fprintf(stdout, "%s pts event %p, fd %d %d\n",
|
||||||
|
__func__, &e->e, e->e.fd, e->ptyfd);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_dup_exec_tty(int to, struct hyper_exec *e)
|
int hyper_dup_exec_tty(int to, struct hyper_exec *e)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd = -1, ret = -1;
|
||||||
char pty[128];
|
char pty[128];
|
||||||
|
|
||||||
|
fprintf(stdout, "%s\n", __func__);
|
||||||
setsid();
|
setsid();
|
||||||
|
|
||||||
if (e->seq) {
|
if (e->seq) {
|
||||||
if (sprintf(pty, "/dev/pts/%d", e->ptyno) < 0) {
|
fd = e->ptyfd;
|
||||||
perror("get pts device name failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
if (sprintf(pty, "/dev/null") < 0) {
|
if (sprintf(pty, "/dev/null") < 0) {
|
||||||
perror("get pts device name failed");
|
perror("get pts device name failed");
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
fd = open(pty, O_RDWR | O_NOCTTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "setup pty device %s for exec\n", pty);
|
|
||||||
|
|
||||||
fd = open(pty, O_RDWR | O_NOCTTY);
|
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
perror("open pty device for execcmd failed");
|
perror("open pty device for execcmd failed");
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e->seq && (ioctl(fd, TIOCSCTTY, NULL) < 0)) {
|
if (e->seq && (ioctl(fd, TIOCSCTTY, NULL) < 0)) {
|
||||||
perror("ioctl pty device for execcmd failed");
|
perror("ioctl pty device for execcmd failed");
|
||||||
return -1;
|
goto out;
|
||||||
}
|
|
||||||
|
|
||||||
if (hyper_send_type_block(to, READY, 0) < 0) {
|
|
||||||
fprintf(stderr, "send ready message to hyper init failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
|
hyper_send_type(to, READY);
|
||||||
|
|
||||||
if (dup2(fd, STDIN_FILENO) < 0) {
|
if (dup2(fd, STDIN_FILENO) < 0) {
|
||||||
perror("dup tty device to stdin failed");
|
perror("dup tty device to stdin failed");
|
||||||
close(fd);
|
goto out;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dup2(fd, STDOUT_FILENO) < 0) {
|
if (dup2(fd, STDOUT_FILENO) < 0) {
|
||||||
perror("dup tty device to stdout failed");
|
perror("dup tty device to stdout failed");
|
||||||
close(fd);
|
goto out;
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dup2(fd, STDERR_FILENO) < 0) {
|
if (e->errseq > 0) {
|
||||||
perror("dup tty device to stderr failed");
|
if (dup2(e->errfd, STDERR_FILENO) < 0) {
|
||||||
close(fd);
|
perror("dup err pipe to stderr failed");
|
||||||
return -1;
|
goto out;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dup2(fd, STDERR_FILENO) < 0) {
|
||||||
|
perror("dup tty device to stderr failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
out:
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
return 0;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_exec_in_container(struct hyper_pod *pod,
|
int hyper_watch_exec_pty(struct hyper_exec *exec, struct hyper_pod *pod)
|
||||||
struct hyper_exec *exec)
|
|
||||||
{
|
{
|
||||||
global_exec = exec;
|
fprintf(stdout, "hyper_init_event container pts event %p, ops %p, fd %d\n",
|
||||||
|
&exec->e, &pts_ops, exec->e.fd);
|
||||||
|
|
||||||
if (hyper_send_type_block(ctl.ctl.fd, EXECCMD, 1) < 0) {
|
|
||||||
global_exec = NULL;
|
|
||||||
fprintf(stderr, "tell pod init EXECCMD failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_add_tail(&exec->list, &pod->ce_head);
|
|
||||||
if (exec->seq == 0)
|
if (exec->seq == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fprintf(stdout, "init container exec pts event %p, ops %p, fd %d\n",
|
if (hyper_init_event(&exec->e, &pts_ops, pod) < 0 ||
|
||||||
&exec->e, &pts_ops, exec->e.fd);
|
hyper_add_event(ctl.efd, &exec->e, EPOLLIN) < 0) {
|
||||||
|
fprintf(stderr, "add container pts master event failed\n");
|
||||||
if (hyper_init_event(&exec->e, &pts_ops, 0, ctl.tty.fd, NULL) < 0 ||
|
|
||||||
hyper_add_event(ctl.efd, &exec->e) < 0) {
|
|
||||||
fprintf(stderr, "add pts master event failed\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
exec->ref++;
|
||||||
|
|
||||||
|
if (exec->errseq == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (hyper_init_event(&exec->errev, &err_ops, pod) < 0 ||
|
||||||
|
hyper_add_event(ctl.efd, &exec->errev, EPOLLIN) < 0) {
|
||||||
|
fprintf(stderr, "add container stderr event failed\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
exec->ref++;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_request_restart_containers(struct hyper_pod *pod)
|
int hyper_enter_container(struct hyper_pod *pod,
|
||||||
|
struct hyper_exec *exec)
|
||||||
{
|
{
|
||||||
int i;
|
int ipcns, utsns, mntns, ret;
|
||||||
struct hyper_exec *exec;
|
struct hyper_container *c;
|
||||||
|
char path[512];
|
||||||
|
|
||||||
pod->code = 0;
|
ret = ipcns = utsns = mntns = -1;
|
||||||
pod->remains = pod->c_num;
|
|
||||||
|
|
||||||
for (i = 0; i < pod->c_num; i++) {
|
c = hyper_find_container(pod, exec->id);
|
||||||
exec = &pod->c[i].exec;
|
if (c == NULL) {
|
||||||
|
fprintf(stderr, "can not find container %s\n", exec->id);
|
||||||
if (hyper_setup_exec_tty(exec) < 0) {
|
|
||||||
fprintf(stdout, "restart setup container tty failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hyper_send_type_block(ctl.ctl.fd, RESTARTCONTAINER, 1) < 0) {
|
|
||||||
fprintf(stderr, "tell container init RESTARTCONTAINER failed\n");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < pod->c_num; i++) {
|
sprintf(path, "/proc/%d/ns/uts", pod->init_pid);
|
||||||
exec = &pod->c[i].exec;
|
utsns = open(path, O_RDONLY| O_CLOEXEC);
|
||||||
|
if (utsns < 0) {
|
||||||
list_add_tail(&exec->list, &pod->ce_head);
|
perror("fail to open utsns of pod init");
|
||||||
if (exec->seq == 0)
|
goto out;
|
||||||
continue;
|
|
||||||
|
|
||||||
if (hyper_init_event(&exec->e, &pts_ops, 0, ctl.tty.fd, NULL) < 0 ||
|
|
||||||
hyper_add_event(ctl.efd, &exec->e) < 0) {
|
|
||||||
fprintf(stderr, "add pts master event failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
sprintf(path, "/proc/%d/ns/ipc", pod->init_pid);
|
||||||
|
ipcns = open(path, O_RDONLY| O_CLOEXEC);
|
||||||
|
if (ipcns < 0) {
|
||||||
|
perror("fail to open ipcns of pod init");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
mntns = c->ns;
|
||||||
|
if (mntns < 0) {
|
||||||
|
perror("fail to open mntns of pod init");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (setns(utsns, CLONE_NEWUTS) < 0 ||
|
||||||
|
setns(ipcns, CLONE_NEWIPC) <0 ||
|
||||||
|
setns(mntns, CLONE_NEWNS) < 0) {
|
||||||
|
perror("fail to enter container ns");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
sprintf(path, "/tmp/hyper/%s/root/%s/", c->id, c->rootfs);
|
||||||
|
fprintf(stdout, "root directory for container is %s, exec %s\n",
|
||||||
|
path, exec->argv[0]);
|
||||||
|
|
||||||
|
/* TODO: wait for container finishing setup root */
|
||||||
|
if (chroot(path) < 0) {
|
||||||
|
perror("chroot for exec command failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
chdir("/");
|
||||||
|
|
||||||
|
ret = hyper_setup_env(c->envs, c->envs_num);
|
||||||
|
out:
|
||||||
|
close(ipcns);
|
||||||
|
close(utsns);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct hyper_exec_arg {
|
||||||
|
struct hyper_pod *pod;
|
||||||
|
struct hyper_exec *exec;
|
||||||
|
int pipe[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int hyper_do_exec_cmd(void *data)
|
||||||
|
{
|
||||||
|
struct hyper_exec_arg *arg = data;
|
||||||
|
struct hyper_exec *exec = arg->exec;
|
||||||
|
struct hyper_pod *pod = arg->pod;
|
||||||
|
int pipe[2] = {-1, -1}, pid;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (exec->id) {
|
||||||
|
char path[512];
|
||||||
|
int pidns;
|
||||||
|
|
||||||
|
sprintf(path, "/proc/%d/ns/pid", pod->init_pid);
|
||||||
|
pidns = open(path, O_RDONLY| O_CLOEXEC);
|
||||||
|
if (pidns < 0) {
|
||||||
|
perror("fail to open pidns of pod init");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enter pidns of pod init, so the children of this process will run in
|
||||||
|
* pidns of pod init, see man 2 setns */
|
||||||
|
if (setns(pidns, CLONE_NEWPID) < 0) {
|
||||||
|
perror("enter pidns of pod init failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
close(pidns);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pipe2(pipe, O_CLOEXEC) < 0) {
|
||||||
|
perror("create pipe in exec command failed");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_watch_exec_pty(exec, pod) < 0) {
|
||||||
|
fprintf(stderr, "add pts master event failed\n");
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = fork();
|
||||||
|
if (pid < 0) {
|
||||||
|
perror("fail to fork");
|
||||||
|
goto out;
|
||||||
|
} else if (pid > 0) {
|
||||||
|
uint32_t type;
|
||||||
|
|
||||||
|
if (hyper_get_type(pipe[0], &type) < 0 || type != READY) {
|
||||||
|
fprintf(stderr, "hyper init doesn't get execcmd ready message\n");
|
||||||
|
hyper_send_type(arg->pipe[1], ERROR);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(stdout, "hyper init get ready message\n");
|
||||||
|
exec->pid = pid;
|
||||||
|
//TODO combin ref++ and add to list.
|
||||||
|
list_add_tail(&exec->list, &pod->exec_head);
|
||||||
|
exec->ref++;
|
||||||
|
fprintf(stdout, "create exec cmd %s pid %d,ref %d\n", exec->argv[0], pid, exec->ref);
|
||||||
|
ret = 0;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (exec->id && hyper_enter_container(pod, exec) < 0) {
|
||||||
|
fprintf(stderr, "enter container ns failed\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_dup_exec_tty(pipe[1], exec) < 0) {
|
||||||
|
fprintf(stderr, "dup pts to exec stdio failed\n");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (execvp(exec->argv[0], exec->argv) < 0) {
|
||||||
|
perror("exec failed");
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = 0;
|
||||||
|
exit:
|
||||||
|
hyper_send_type(pipe[1], ERROR);
|
||||||
|
_exit(ret);
|
||||||
|
|
||||||
|
out:
|
||||||
|
hyper_send_type(arg->pipe[1], ret ? ERROR : READY);
|
||||||
|
close(pipe[0]);
|
||||||
|
close(pipe[1]);
|
||||||
|
_exit(ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void hyper_free_exec(struct hyper_exec *exec)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
free(exec->id);
|
||||||
|
|
||||||
|
for (i = 0; i < exec->argc; i++) {
|
||||||
|
//fprintf(stdout, "argv %d %s\n", i, exec->argv[i]);
|
||||||
|
free(exec->argv[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
free(exec->argv);
|
||||||
|
free(exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_exec_cmd(char *json, int length)
|
int hyper_exec_cmd(char *json, int length)
|
||||||
{
|
{
|
||||||
struct hyper_exec *exec;
|
struct hyper_exec *exec;
|
||||||
struct hyper_pod *pod = &global_pod;
|
struct hyper_pod *pod = &global_pod;
|
||||||
int pid, pipe[2];
|
int stacksize = getpagesize() * 4;
|
||||||
|
void *stack = NULL;
|
||||||
|
struct hyper_exec_arg arg = {
|
||||||
|
.pod = pod,
|
||||||
|
.exec = NULL,
|
||||||
|
.pipe = {-1, -1},
|
||||||
|
};
|
||||||
|
int pid, ret = -1;
|
||||||
|
uint32_t type;
|
||||||
|
|
||||||
fprintf(stdout, "call hyper_exec_cmd, json %s, len %d\n", json, length);
|
fprintf(stdout, "call hyper_exec_cmd, json %s, len %d\n", json, length);
|
||||||
|
|
||||||
exec = hyper_parse_execcmd(json, length);
|
exec = hyper_parse_execcmd(json, length);
|
||||||
if (exec == NULL) {
|
if (exec == NULL) {
|
||||||
fprintf(stderr, "parse exec cmd failed\n");
|
fprintf(stderr, "parse exec cmd failed\n");
|
||||||
return -1;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exec->argv == NULL) {
|
if (exec->argv == NULL) {
|
||||||
fprintf(stderr, "cmd is %p, seq %" PRIu64 ", container %s\n",
|
fprintf(stderr, "cmd is %p, seq %" PRIu64 ", container %s\n",
|
||||||
exec->argv, exec->seq, exec->id);
|
exec->argv, exec->seq, exec->id);
|
||||||
return -1;
|
goto free_exec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hyper_setup_exec_tty(exec) < 0) {
|
if (hyper_setup_exec_tty(exec) < 0) {
|
||||||
fprintf(stderr, "setup exec tty failed\n");
|
fprintf(stderr, "setup exec tty failed\n");
|
||||||
return -1;
|
goto free_exec;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (exec->id) {
|
if (pipe2(arg.pipe, O_CLOEXEC) < 0) {
|
||||||
if (hyper_exec_in_container(pod, exec) < 0) {
|
|
||||||
fprintf(stderr, "notify container exec failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (socketpair(PF_UNIX, SOCK_STREAM, 0, pipe) < 0) {
|
|
||||||
perror("create pipe between pod init execcmd failed");
|
perror("create pipe between pod init execcmd failed");
|
||||||
return -1;
|
goto close_tty;
|
||||||
}
|
}
|
||||||
|
|
||||||
pid = fork();
|
arg.exec = exec;
|
||||||
|
|
||||||
|
stack = malloc(stacksize);
|
||||||
|
if (stack == NULL) {
|
||||||
|
perror("fail to allocate stack for container init");
|
||||||
|
goto close_tty;
|
||||||
|
}
|
||||||
|
|
||||||
|
pid = clone(hyper_do_exec_cmd, stack + stacksize, CLONE_VM| CLONE_FILES| SIGCHLD, &arg);
|
||||||
|
fprintf(stdout, "do_exec_cmd pid %d\n", pid);
|
||||||
|
free(stack);
|
||||||
if (pid < 0) {
|
if (pid < 0) {
|
||||||
fprintf(stderr, "fork failed\n");
|
perror("clone hyper_do_exec_cmd failed");
|
||||||
return -1;
|
goto close_tty;
|
||||||
} else if (pid > 0) {
|
|
||||||
uint32_t type;
|
|
||||||
|
|
||||||
if (hyper_get_type_block(pipe[0], &type) < 0 || type != READY) {
|
|
||||||
fprintf(stderr, "hyper init doesn't get execcmd ready message\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(pipe[0]);
|
|
||||||
close(pipe[1]);
|
|
||||||
fprintf(stdout, "hyper init get ready message\n");
|
|
||||||
exec->pid = pid;
|
|
||||||
fprintf(stdout, "create exec cmd %s pid %d\n", exec->argv[0], pid);
|
|
||||||
|
|
||||||
list_add_tail(&exec->list, &pod->pe_head);
|
|
||||||
if (exec->seq == 0)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
fprintf(stdout, "init pod exec pts event %p, ops %p, fd %d\n",
|
|
||||||
&exec->e, &pts_ops, exec->e.fd);
|
|
||||||
if (hyper_init_event(&exec->e, &pts_ops, 0, ctl.tty.fd, NULL) < 0 ||
|
|
||||||
hyper_add_event(ctl.efd, &exec->e) < 0) {
|
|
||||||
fprintf(stderr, "add pts master event failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (hyper_dup_exec_tty(pipe[1], exec) < 0) {
|
if (hyper_get_type(arg.pipe[0], &type) < 0 || type != READY) {
|
||||||
fprintf(stderr, "dup pts to exec stdio failed\n");
|
fprintf(stderr, "hyper init doesn't get execcmd ready message\n");
|
||||||
_exit(-1);
|
goto close_tty;
|
||||||
}
|
}
|
||||||
|
|
||||||
close(pipe[0]);
|
fprintf(stdout, "%s get ready message %"PRIu32 "\n", __func__, type);
|
||||||
close(pipe[1]);
|
ret = 0;
|
||||||
|
out:
|
||||||
if (execvp(exec->argv[0], exec->argv) < 0) {
|
close(arg.pipe[0]);
|
||||||
perror("exec failed");
|
close(arg.pipe[1]);
|
||||||
_exit(-1);
|
return ret;
|
||||||
}
|
close_tty:
|
||||||
|
close(exec->ptyfd);
|
||||||
_exit(0);
|
close(exec->errfd);
|
||||||
|
close(exec->e.fd);
|
||||||
|
free_exec:
|
||||||
|
hyper_free_exec(exec);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_container_execcmd(struct hyper_pod *pod)
|
static int hyper_send_pod_finished(struct hyper_pod *pod)
|
||||||
{
|
{
|
||||||
struct hyper_exec *exec = global_exec;
|
int ret = -1;
|
||||||
struct hyper_container *container = NULL;
|
struct hyper_container *c;
|
||||||
int fd, pid, sock = pod->ctl.fd;
|
uint8_t *data = NULL, *new;
|
||||||
char root[512]; int pipe[2];
|
int c_num = 0;
|
||||||
|
|
||||||
global_exec = NULL;
|
list_for_each_entry(c, &pod->containers, list) {
|
||||||
|
c_num++;
|
||||||
|
new = realloc(data, c_num * 4);
|
||||||
|
if (new == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
container = hyper_find_container(pod, exec->id);
|
hyper_set_be32(new + ((c_num - 1) * 4), c->exec.code);
|
||||||
if (container == NULL) {
|
data = new;
|
||||||
fprintf(stderr, "can not find container %s\n", exec->id);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sprintf(root, "/tmp/hyper/%s/devpts/", exec->id) < 0) {
|
ret = hyper_send_msg_block(ctl.chan.fd, PODFINISHED, c_num * 4, data);
|
||||||
fprintf(stderr, "get container %s pts path failed\n", exec->id);
|
out:
|
||||||
return -1;
|
free(data);
|
||||||
}
|
return ret;
|
||||||
|
|
||||||
if (socketpair(PF_UNIX, SOCK_STREAM, 0, pipe) < 0) {
|
|
||||||
perror("create pipe between pod init execcmd failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
pid = fork();
|
|
||||||
if (pid < 0) {
|
|
||||||
fprintf(stderr, "container init fork failed\n");
|
|
||||||
return -1;
|
|
||||||
} else if (pid > 0) {
|
|
||||||
uint32_t type;
|
|
||||||
|
|
||||||
if (hyper_get_type_block(pipe[0], &type) < 0 || type != READY) {
|
|
||||||
fprintf(stderr, "pod init get execcmd ready message failed\n");
|
|
||||||
hyper_send_type_block(sock, ERROR, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(pipe[0]);
|
|
||||||
close(pipe[1]);
|
|
||||||
fprintf(stdout, "pod init get ready message\n");
|
|
||||||
|
|
||||||
exec->pid = pid;
|
|
||||||
fprintf(stdout, "create exec cmd %s pid %d\n", exec->argv[0], pid);
|
|
||||||
|
|
||||||
if (hyper_send_type_block(sock, ACK, 0) < 0)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(pipe[0]);
|
|
||||||
sprintf(root, "/proc/%d/ns/mnt", container->exec.pid);
|
|
||||||
|
|
||||||
fprintf(stdout, "container %s, init pid %d\n",
|
|
||||||
exec->id, container->exec.pid);
|
|
||||||
|
|
||||||
fd = open(root, O_RDONLY);
|
|
||||||
if (fd < 0) {
|
|
||||||
perror("fail to open container mnt ns\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (syscall(SYS_setns, fd, CLONE_NEWNS) < 0) {
|
|
||||||
perror("enter mnt ns failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
sprintf(root, "/tmp/hyper/%s/root/%s/",
|
|
||||||
container->id, container->rootfs);
|
|
||||||
|
|
||||||
fprintf(stdout, "root directory for container is %s, exec %s\n",
|
|
||||||
root, exec->argv[0]);
|
|
||||||
|
|
||||||
/* TODO: wait for container finishing setup root */
|
|
||||||
if (chroot(root) < 0) {
|
|
||||||
perror("chroot for exec command failed");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
chdir("/");
|
|
||||||
|
|
||||||
if (hyper_dup_exec_tty(pipe[1], exec)) {
|
|
||||||
fprintf(stderr, "dup pts to stdio failed\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
close(pipe[1]);
|
|
||||||
if (execvp(exec->argv[0], exec->argv) < 0)
|
|
||||||
perror("exec failed");
|
|
||||||
|
|
||||||
_exit(-1);
|
|
||||||
fail:
|
|
||||||
hyper_send_type_block(pipe[1], ERROR, 0);
|
|
||||||
_exit(-1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_release_exec(struct hyper_exec *exec,
|
int hyper_release_exec(struct hyper_exec *exec,
|
||||||
struct hyper_pod *pod)
|
struct hyper_pod *pod)
|
||||||
{
|
{
|
||||||
int i;
|
if (--exec->ref != 0) {
|
||||||
|
fprintf(stdout, "still have %d user of exec\n", exec->ref);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
close(exec->e.fd);
|
/* exec has no pty or the pty user already exited */
|
||||||
free(exec->pty);
|
fprintf(stdout, "last user of exec exit, release\n");
|
||||||
|
|
||||||
|
hyper_reset_event(&exec->e);
|
||||||
|
hyper_reset_event(&exec->errev);
|
||||||
|
|
||||||
list_del_init(&exec->list);
|
list_del_init(&exec->list);
|
||||||
|
|
||||||
@@ -436,41 +568,26 @@ int hyper_release_exec(struct hyper_exec *exec,
|
|||||||
fprintf(stdout, "%s container init exited, type %d, remains %d, policy %d\n",
|
fprintf(stdout, "%s container init exited, type %d, remains %d, policy %d\n",
|
||||||
__func__, pod->type, pod->remains, pod->policy);
|
__func__, pod->type, pod->remains, pod->policy);
|
||||||
|
|
||||||
/* stop pod, should not restart container */
|
// TODO send finish of this container and full cleanup
|
||||||
if (pod->type == STOPPOD)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (exec->code)
|
|
||||||
pod->code = exec->code;
|
|
||||||
|
|
||||||
if (--pod->remains > 0)
|
if (--pod->remains > 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* should shutdown? */
|
if (pod->type == STOPPOD) {
|
||||||
if (pod->policy == POLICY_NEVER ||
|
/* stop pod manually, hyper doesn't care the pod finished codes */
|
||||||
((pod->policy == POLICY_ONFAILURE) && pod->code == 0)) {
|
hyper_send_msg_block(ctl.chan.fd, ACK, 0, NULL);
|
||||||
hyper_shutdown(pod);
|
} else if (pod->type == DESTROYPOD) {
|
||||||
return 0;
|
/* shutdown vm manually, hyper doesn't care the pod finished codes */
|
||||||
}
|
hyper_shutdown();
|
||||||
|
} else {
|
||||||
if (hyper_request_restart_containers(pod) < 0) {
|
/* send out pod finish message, hyper will decide if restart pod or not */
|
||||||
fprintf(stderr, "restart container failed\n");
|
hyper_send_pod_finished(pod);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hyper_cleanup_pod(pod);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
free(exec->id);
|
hyper_free_exec(exec);
|
||||||
|
|
||||||
for (i = 0; i < exec->argc; i++) {
|
|
||||||
fprintf(stdout, "argv %d %s\n", i, exec->argv[i]);
|
|
||||||
free(exec->argv[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
free(exec->argv);
|
|
||||||
free(exec);
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -493,17 +610,8 @@ struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq)
|
|||||||
{
|
{
|
||||||
struct hyper_exec *exec;
|
struct hyper_exec *exec;
|
||||||
|
|
||||||
list_for_each_entry(exec, &pod->ce_head, list) {
|
list_for_each_entry(exec, &pod->exec_head, list) {
|
||||||
fprintf(stdout, "container exec seq %" PRIu64 ", seq %" PRIu64 "\n",
|
fprintf(stdout, "exec seq %" PRIu64 ", seq %" PRIu64 "\n",
|
||||||
exec->seq, seq);
|
|
||||||
if (exec->seq != seq)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
return exec;
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(exec, &pod->pe_head, list) {
|
|
||||||
fprintf(stdout, "pod exec seq %" PRIu64 ", seq %" PRIu64 "\n",
|
|
||||||
exec->seq, seq);
|
exec->seq, seq);
|
||||||
if (exec->seq != seq)
|
if (exec->seq != seq)
|
||||||
continue;
|
continue;
|
||||||
@@ -514,35 +622,28 @@ struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_send_exec_eof(int to, struct hyper_pod *pod,
|
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code)
|
||||||
struct list_head *head, int pid,
|
|
||||||
uint8_t code)
|
|
||||||
{
|
{
|
||||||
struct hyper_exec *exec;
|
struct hyper_exec *exec;
|
||||||
uint8_t seq[12];
|
|
||||||
|
|
||||||
exec = hyper_find_exec_by_pid(head, pid);
|
exec = hyper_find_exec_by_pid(&pod->exec_head, pid);
|
||||||
if (exec == NULL) {
|
if (exec == NULL) {
|
||||||
fprintf(stdout, "can not find exec whose pid is %d\n",
|
fprintf(stdout, "can not find exec whose pid is %d\n",
|
||||||
pid);
|
pid);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
fprintf(stdout, "%s exec pid %d, seq %" PRIu64 ", container %s\n",
|
fprintf(stdout, "%s exec exit pid %d, seq %" PRIu64 ", container %s\n",
|
||||||
__func__, exec->pid, exec->seq, exec->id ? exec->id : "pod");
|
__func__, exec->pid, exec->seq, exec->id ? exec->id : "pod");
|
||||||
|
|
||||||
exec->code = code;
|
exec->code = code;
|
||||||
|
exec->exit = 1;
|
||||||
|
|
||||||
if (exec->seq == 0)
|
close(exec->ptyfd);
|
||||||
goto out;
|
exec->ptyfd = -1;
|
||||||
|
close(exec->errfd);
|
||||||
|
exec->errfd = -1;
|
||||||
|
|
||||||
hyper_set_be64(seq, exec->seq);
|
|
||||||
hyper_set_be32(seq + 8, 12);
|
|
||||||
if (hyper_send_data(to, seq, 12) < 0) {
|
|
||||||
fprintf(stderr, "pod signal_loop send finishcmd failed\n");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
out:
|
|
||||||
hyper_release_exec(exec, pod);
|
hyper_release_exec(exec, pod);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -551,9 +652,16 @@ out:
|
|||||||
void hyper_cleanup_exec(struct hyper_pod *pod)
|
void hyper_cleanup_exec(struct hyper_pod *pod)
|
||||||
{
|
{
|
||||||
struct hyper_exec *exec, *next;
|
struct hyper_exec *exec, *next;
|
||||||
|
uint8_t buf[12];
|
||||||
|
|
||||||
list_for_each_entry_safe(exec, next, &pod->ce_head, list) {
|
if (hyper_setfd_block(ctl.tty.fd) < 0)
|
||||||
fprintf(stdout, "cleanup container exec seq %" PRIu64 "\n", exec->seq);
|
return;
|
||||||
hyper_release_exec(exec, pod);
|
|
||||||
|
hyper_set_be32(buf + 8, 12);
|
||||||
|
list_for_each_entry_safe(exec, next, &pod->exec_head, list) {
|
||||||
|
fprintf(stdout, "send eof for exec seq %" PRIu64 "\n", exec->seq);
|
||||||
|
hyper_set_be64(buf, exec->seq);
|
||||||
|
if (hyper_send_data(ctl.tty.fd, buf, 12) < 0)
|
||||||
|
fprintf(stderr, "send eof failed\n");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -7,15 +7,20 @@
|
|||||||
struct hyper_exec {
|
struct hyper_exec {
|
||||||
struct list_head list;
|
struct list_head list;
|
||||||
struct hyper_event e;
|
struct hyper_event e;
|
||||||
|
struct hyper_event errev;
|
||||||
char *id;
|
char *id;
|
||||||
char *pty;
|
|
||||||
char **argv;
|
char **argv;
|
||||||
int argc;
|
int argc;
|
||||||
uint64_t seq;
|
uint64_t seq;
|
||||||
|
uint64_t errseq;
|
||||||
int pid;
|
int pid;
|
||||||
int ptyno;
|
int ptyno;
|
||||||
int init;
|
int init;
|
||||||
|
int ptyfd;
|
||||||
|
int errfd;
|
||||||
uint8_t code;
|
uint8_t code;
|
||||||
|
uint8_t exit;
|
||||||
|
uint8_t ref;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_pod;
|
struct hyper_pod;
|
||||||
@@ -27,9 +32,8 @@ int hyper_setup_exec_tty(struct hyper_exec *e);
|
|||||||
int hyper_dup_exec_tty(int fd, struct hyper_exec *e);
|
int hyper_dup_exec_tty(int fd, struct hyper_exec *e);
|
||||||
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
|
struct hyper_exec *hyper_find_exec_by_pid(struct list_head *head, int pid);
|
||||||
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
|
struct hyper_exec *hyper_find_exec_by_seq(struct hyper_pod *pod, uint64_t seq);
|
||||||
int hyper_send_exec_eof(int to, struct hyper_pod *pod,
|
int hyper_handle_exec_exit(struct hyper_pod *pod, int pid, uint8_t code);
|
||||||
struct list_head *head, int pid,
|
int hyper_watch_exec_pty(struct hyper_exec *exec, struct hyper_pod *pod);
|
||||||
uint8_t code);
|
|
||||||
void hyper_cleanup_exec(struct hyper_pod *pod);
|
void hyper_cleanup_exec(struct hyper_pod *pod);
|
||||||
|
|
||||||
extern struct hyper_event_ops pts_ops;
|
extern struct hyper_event_ops pts_ops;
|
||||||
|
|||||||
+35
-13
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _DVM_H_
|
#ifndef _HYPER_H_
|
||||||
#define _DVM_H_
|
#define _HYPER_H_
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -10,20 +10,25 @@
|
|||||||
#include "container.h"
|
#include "container.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
SETDVM,
|
RESERVED,
|
||||||
STARTPOD,
|
STARTPOD,
|
||||||
GETPOD,
|
GETPOD,
|
||||||
STOPPOD,
|
STOPPOD,
|
||||||
DESTROYPOD,
|
DESTROYPOD,
|
||||||
RESTARTCONTAINER,
|
RESTARTCONTAINER,
|
||||||
EXECCMD,
|
EXECCMD,
|
||||||
FINISHCMD,
|
CMDFINISHED,
|
||||||
READY,
|
READY,
|
||||||
ACK,
|
ACK,
|
||||||
ERROR,
|
ERROR,
|
||||||
WINSIZE,
|
WINSIZE,
|
||||||
PING,
|
PING,
|
||||||
FINISH,
|
PODFINISHED,
|
||||||
|
NEXT,
|
||||||
|
WRITEFILE,
|
||||||
|
READFILE,
|
||||||
|
NEWCONTAINER,
|
||||||
|
KILLCONTAINER,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
@@ -36,23 +41,22 @@ struct hyper_pod {
|
|||||||
struct hyper_container *c;
|
struct hyper_container *c;
|
||||||
struct hyper_interface *iface;
|
struct hyper_interface *iface;
|
||||||
struct hyper_route *rt;
|
struct hyper_route *rt;
|
||||||
struct list_head pe_head;
|
char **dns;
|
||||||
struct list_head ce_head;
|
struct list_head containers;
|
||||||
|
struct list_head exec_head;
|
||||||
char *hostname;
|
char *hostname;
|
||||||
char *tag;
|
char *share_tag;
|
||||||
char *channel;
|
|
||||||
int init_pid;
|
int init_pid;
|
||||||
uint32_t c_num;
|
|
||||||
uint32_t i_num;
|
uint32_t i_num;
|
||||||
uint32_t r_num;
|
uint32_t r_num;
|
||||||
uint32_t e_num;
|
uint32_t e_num;
|
||||||
|
uint32_t d_num;
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
uint32_t code;
|
/* how many containers are running */
|
||||||
uint32_t remains;
|
uint32_t remains;
|
||||||
uint8_t policy;
|
uint8_t policy;
|
||||||
int efd;
|
int efd;
|
||||||
struct hyper_event sig;
|
struct hyper_event sig;
|
||||||
struct hyper_event ctl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hyper_win_size {
|
struct hyper_win_size {
|
||||||
@@ -62,17 +66,35 @@ struct hyper_win_size {
|
|||||||
uint64_t seq;
|
uint64_t seq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct hyper_killer {
|
||||||
|
char *id;
|
||||||
|
int signal;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hyper_reader {
|
||||||
|
char *id;
|
||||||
|
char *file;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct hyper_writter {
|
||||||
|
char *id;
|
||||||
|
char *file;
|
||||||
|
uint8_t *data;
|
||||||
|
int len;
|
||||||
|
};
|
||||||
|
|
||||||
struct hyper_ctl {
|
struct hyper_ctl {
|
||||||
int efd;
|
int efd;
|
||||||
struct hyper_event sig;
|
struct hyper_event sig;
|
||||||
struct hyper_event tty;
|
struct hyper_event tty;
|
||||||
struct hyper_event chan;
|
struct hyper_event chan;
|
||||||
struct hyper_event ctl;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
int hyper_mkdir(char *hyper_path);
|
int hyper_mkdir(char *hyper_path);
|
||||||
int hyper_open_serial(char *tty);
|
int hyper_open_serial(char *tty);
|
||||||
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
struct hyper_container *hyper_find_container(struct hyper_pod *pod, char *id);
|
||||||
|
int hyper_start_containers(struct hyper_pod *pod);
|
||||||
|
void hyper_cleanup_pod(struct hyper_pod *pod);
|
||||||
|
|
||||||
extern struct hyper_pod global_pod;
|
extern struct hyper_pod global_pod;
|
||||||
extern struct hyper_ctl ctl;
|
extern struct hyper_ctl ctl;
|
||||||
|
|||||||
+773
-415
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;
|
int i;
|
||||||
jsmntok_t *token;
|
jsmntok_t *token;
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
int num = 0;
|
||||||
|
int out = 0;
|
||||||
|
|
||||||
for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
|
for (; parser->pos < len && js[parser->pos] != '\0' && !out; parser->pos++) {
|
||||||
char c;
|
char c;
|
||||||
jsmntype_t type;
|
jsmntype_t type;
|
||||||
|
|
||||||
c = js[parser->pos];
|
c = js[parser->pos];
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '{': case '[':
|
case '{':
|
||||||
|
num++;
|
||||||
|
case '[':
|
||||||
count++;
|
count++;
|
||||||
if (tokens == NULL)
|
if (tokens == NULL)
|
||||||
break;
|
break;
|
||||||
@@ -189,7 +193,10 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
|||||||
token->start = parser->pos;
|
token->start = parser->pos;
|
||||||
parser->toksuper = parser->toknext - 1;
|
parser->toksuper = parser->toknext - 1;
|
||||||
break;
|
break;
|
||||||
case '}': case ']':
|
case '}':
|
||||||
|
if (--num <= 0)
|
||||||
|
out = 1;
|
||||||
|
case ']':
|
||||||
if (tokens == NULL)
|
if (tokens == NULL)
|
||||||
break;
|
break;
|
||||||
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
|
||||||
@@ -221,7 +228,7 @@ jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
|
|||||||
|
|
||||||
parser->toksuper = -1;
|
parser->toksuper = -1;
|
||||||
token->end = parser->pos + 1;
|
token->end = parser->pos + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Error if unmatched closing bracket */
|
/* Error if unmatched closing bracket */
|
||||||
|
|||||||
@@ -7,8 +7,11 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
|
#include "util.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
void hyper_set_be32(uint8_t *buf, uint32_t val)
|
void hyper_set_be32(uint8_t *buf, uint32_t val)
|
||||||
{
|
{
|
||||||
@@ -55,7 +58,9 @@ int hyper_send_data(int fd, uint8_t *data, uint32_t len)
|
|||||||
perror("send hyper data failed");
|
perror("send hyper data failed");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
#if WITH_VBOX
|
||||||
|
tcdrain(fd);
|
||||||
|
#endif
|
||||||
length += size;
|
length += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,7 +91,7 @@ int hyper_send_type(int fd, uint32_t type)
|
|||||||
return hyper_send_msg(fd, type, 0, NULL);
|
return hyper_send_msg(fd, type, 0, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_get_type_block(int fd, uint32_t *type)
|
int hyper_get_type(int fd, uint32_t *type)
|
||||||
{
|
{
|
||||||
int len = 0, size;
|
int len = 0, size;
|
||||||
uint8_t buf[8];
|
uint8_t buf[8];
|
||||||
@@ -107,42 +112,20 @@ int hyper_get_type_block(int fd, uint32_t *type)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack)
|
int hyper_send_msg_block(int fd, uint32_t type, uint32_t len, uint8_t *data)
|
||||||
{
|
{
|
||||||
int ret = 0, flags;
|
int ret, flags;
|
||||||
uint32_t t;
|
|
||||||
|
|
||||||
flags = fcntl(fd, F_GETFL, 0);
|
flags = hyper_setfd_block(fd);
|
||||||
if (flags < 0) {
|
if (flags < 0) {
|
||||||
fprintf(stderr, "get fd flag failed\n");
|
fprintf(stderr, "%s fail to set fd block\n", __func__);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fcntl(fd, F_SETFL, flags & ~O_NONBLOCK) < 0) {
|
ret = hyper_send_msg(fd, type, len, data);
|
||||||
perror("set fd BLOCK failed");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = hyper_send_msg(fd, type, 0, NULL);
|
if (fcntl(fd, F_SETFL, flags) < 0) {
|
||||||
if (ret < 0)
|
perror("restore fd flag failed");
|
||||||
goto out;
|
|
||||||
|
|
||||||
if (need_ack == 0)
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
ret = hyper_get_type_block(fd, &t);
|
|
||||||
if (ret < 0) {
|
|
||||||
fprintf(stderr, "can not get type\n");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
|
|
||||||
fprintf(stdout, "get type %" PRIu32"\n", type);
|
|
||||||
|
|
||||||
if (t != ACK)
|
|
||||||
ret = -1;
|
|
||||||
out:
|
|
||||||
if (fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
|
|
||||||
perror("set fd BLOCK failed");
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -303,14 +286,17 @@ static int hyper_remove_nic(char *device)
|
|||||||
{
|
{
|
||||||
char path[256], real[128];
|
char path[256], real[128];
|
||||||
int fd;
|
int fd;
|
||||||
|
ssize_t size;
|
||||||
|
|
||||||
sprintf(path, "/sys/class/net/%s", device);
|
sprintf(path, "/sys/class/net/%s", device);
|
||||||
|
|
||||||
if (readlink(path, real, 128) < 0) {
|
size = readlink(path, real, 128);
|
||||||
|
if (size < 0 || size > 127) {
|
||||||
perror("fail to read link directory");
|
perror("fail to read link directory");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
real[size] = '\0';
|
||||||
sprintf(path, "/sys/%s/../../../remove", real + 5);
|
sprintf(path, "/sys/%s/../../../remove", real + 5);
|
||||||
|
|
||||||
fprintf(stdout, "get net sys path %s\n", path);
|
fprintf(stdout, "get net sys path %s\n", path);
|
||||||
@@ -672,6 +658,11 @@ static int hyper_cleanup_interface(struct rtnl_handle *rth,
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Don't down&remove lo device */
|
||||||
|
if (strcmp(iface->device, "lo") == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
if (hyper_down_nic(rth, iface->ifindex) < 0) {
|
if (hyper_down_nic(rth, iface->ifindex) < 0) {
|
||||||
fprintf(stderr, "up device %d failed\n", iface->ifindex);
|
fprintf(stderr, "up device %d failed\n", iface->ifindex);
|
||||||
return -1;
|
return -1;
|
||||||
@@ -791,3 +782,64 @@ void hyper_cleanup_network(struct hyper_pod *pod)
|
|||||||
pod->i_num = 0;
|
pod->i_num = 0;
|
||||||
netlink_close(&rth);
|
netlink_close(&rth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,10 +48,12 @@ void hyper_set_be64(uint8_t *buf, uint64_t val);
|
|||||||
uint64_t hyper_get_be64(uint8_t *buf);
|
uint64_t hyper_get_be64(uint8_t *buf);
|
||||||
int hyper_setup_network(struct hyper_pod *pod);
|
int hyper_setup_network(struct hyper_pod *pod);
|
||||||
void hyper_cleanup_network(struct hyper_pod *pod);
|
void hyper_cleanup_network(struct hyper_pod *pod);
|
||||||
int hyper_get_type_block(int fd, uint32_t *type);
|
int hyper_setup_dns(struct hyper_pod *pod);
|
||||||
|
void hyper_cleanup_dns(struct hyper_pod *pod);
|
||||||
|
int hyper_get_type(int fd, uint32_t *type);
|
||||||
int hyper_send_type(int fd, uint32_t type);
|
int hyper_send_type(int fd, uint32_t type);
|
||||||
int hyper_send_type_block(int fd, uint32_t type, int need_ack);
|
int hyper_send_type_block(int fd, uint32_t type, int need_ack);
|
||||||
int hyper_send_msg(int fd, uint32_t type, uint32_t len,
|
int hyper_send_msg(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||||
uint8_t *message);
|
int hyper_send_msg_block(int fd, uint32_t type, uint32_t len, uint8_t *data);
|
||||||
int hyper_send_data(int fd, uint8_t *data, uint32_t len);
|
int hyper_send_data(int fd, uint8_t *data, uint32_t len);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+626
-115
File diff suppressed because it is too large
Load Diff
+7
-2
@@ -1,5 +1,5 @@
|
|||||||
#ifndef _DVM_JSON_H_
|
#ifndef _PARSE_H_
|
||||||
#define _DVM_JSON_H_
|
#define _PARSE_H_
|
||||||
|
|
||||||
#include "hyper.h"
|
#include "hyper.h"
|
||||||
#include "jsmn.h"
|
#include "jsmn.h"
|
||||||
@@ -9,5 +9,10 @@ struct hyper_exec *hyper_parse_execcmd(char *json, int length);
|
|||||||
char *json_token_str(char *js, jsmntok_t *t);
|
char *json_token_str(char *js, jsmntok_t *t);
|
||||||
int json_token_streq(char *js, jsmntok_t *t, char *s);
|
int json_token_streq(char *js, jsmntok_t *t, char *s);
|
||||||
int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length);
|
int hyper_parse_winsize(struct hyper_win_size *ws, char *json, int length);
|
||||||
|
int hyper_parse_kill_container(struct hyper_killer *killer, char *json, int length);
|
||||||
|
int hyper_parse_write_file(struct hyper_writter *writter, char *json, int length);
|
||||||
|
int hyper_parse_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);
|
||||||
|
|
||||||
#endif
|
#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
|
||||||
+177
-75
@@ -11,17 +11,36 @@
|
|||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
#include <sys/reboot.h>
|
#include <sys/reboot.h>
|
||||||
#include <linux/reboot.h>
|
#include <linux/reboot.h>
|
||||||
|
|
||||||
#include "net.h"
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "hyper.h"
|
||||||
|
#include "container.h"
|
||||||
|
#include "../config.h"
|
||||||
|
|
||||||
char *read_cmdline(void)
|
char *read_cmdline(void)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hyper_setup_env(struct env *envs, int num)
|
||||||
|
{
|
||||||
|
int i, ret = 0;
|
||||||
|
struct env *env;
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++) {
|
||||||
|
env = &envs[i];
|
||||||
|
if (setenv(env->env, env->value, 1) < 0) {
|
||||||
|
perror("fail to setup env");
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int hyper_list_dir(char *path)
|
int hyper_list_dir(char *path)
|
||||||
{
|
{
|
||||||
struct dirent **list;
|
struct dirent **list;
|
||||||
@@ -38,12 +57,47 @@ int hyper_list_dir(char *path)
|
|||||||
for (i = 0; i < num; i++) {
|
for (i = 0; i < num; i++) {
|
||||||
dir = list[i];
|
dir = list[i];
|
||||||
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
fprintf(stdout, "%s get %s\n", path, dir->d_name);
|
||||||
|
free(dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(list);
|
free(list);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hyper_find_sd(char *prefix, char *addr, char **dev) {
|
||||||
|
struct dirent **list;
|
||||||
|
struct dirent *dir;
|
||||||
|
char path[512];
|
||||||
|
int i, num;
|
||||||
|
|
||||||
|
sprintf(path, "%s/sys/class/scsi_disk/0:0:%s/device/block/", prefix, 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);
|
||||||
|
free(*dev);
|
||||||
|
*dev = strdup(dir->d_name);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < num; i++)
|
||||||
|
free(list[i]);
|
||||||
|
|
||||||
|
free(list);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int hyper_mkdir(char *hyper_path)
|
int hyper_mkdir(char *hyper_path)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@@ -86,6 +140,101 @@ int hyper_mkdir(char *hyper_path)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#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)
|
int hyper_open_channel(char *channel, int mode)
|
||||||
{
|
{
|
||||||
struct dirent **list;
|
struct dirent **list;
|
||||||
@@ -133,7 +282,7 @@ int hyper_open_channel(char *channel, int mode)
|
|||||||
fprintf(stdout, "open hyper channel %s\n", path);
|
fprintf(stdout, "open hyper channel %s\n", path);
|
||||||
fd = open(path, O_RDWR | O_CLOEXEC | mode);
|
fd = open(path, O_RDWR | O_CLOEXEC | mode);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
perror("fail to open channel deice");
|
perror("fail to open channel device");
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -142,34 +291,22 @@ int hyper_open_channel(char *channel, int mode)
|
|||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int hyper_insmod(char *module)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
int hyper_open_serial_dev(char *tty)
|
int hyper_open_serial_dev(char *tty)
|
||||||
{
|
{
|
||||||
int fd = open(tty, O_RDWR | O_CLOEXEC | O_NOCTTY);
|
int fd = open(tty, O_RDWR | O_CLOEXEC | O_NOCTTY);
|
||||||
|
|
||||||
if (fd < 0) {
|
if (fd < 0)
|
||||||
perror("fail to open tty device");
|
perror("fail to open tty device");
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fd;
|
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 hyper_setfd_cloexec(int fd)
|
||||||
{
|
{
|
||||||
int flags = fcntl(fd, F_GETFD);
|
int flags = fcntl(fd, F_GETFD);
|
||||||
@@ -201,7 +338,7 @@ int hyper_setfd_block(int fd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hyper_setfd_nonblock(int fd)
|
int hyper_setfd_nonblock(int fd)
|
||||||
@@ -218,10 +355,25 @@ int hyper_setfd_nonblock(int fd)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hyper_socketpair(int domain, int type, int protocol, int sv[2])
|
||||||
|
{
|
||||||
|
if (socketpair(domain, type, protocol, sv) < 0) {
|
||||||
|
perror("socketpair failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hyper_setfd_cloexec(sv[0]) < 0 ||
|
||||||
|
hyper_setfd_cloexec(sv[1]) < 0) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyper_unmount_all(void)
|
static void hyper_unmount_all(void)
|
||||||
{
|
{
|
||||||
FILE *mtab;
|
FILE *mtab;
|
||||||
struct mntent *mnt;
|
struct mntent *mnt;
|
||||||
@@ -266,59 +418,9 @@ void hyper_unmount_all(void)
|
|||||||
sync();
|
sync();
|
||||||
}
|
}
|
||||||
|
|
||||||
void hyper_kill_all(void)
|
void hyper_shutdown()
|
||||||
{
|
{
|
||||||
int npids = 0;
|
hyper_send_msg_block(ctl.chan.fd, ACK, 0, NULL);
|
||||||
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_unmount_all();
|
hyper_unmount_all();
|
||||||
|
|
||||||
reboot(LINUX_REBOOT_CMD_POWER_OFF);
|
reboot(LINUX_REBOOT_CMD_POWER_OFF);
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-5
@@ -1,18 +1,30 @@
|
|||||||
#ifndef _UTIL_H_
|
#ifndef _UTIL_H_
|
||||||
#define _UTIL_H_
|
#define _UTIL_H_
|
||||||
|
|
||||||
#include "hyper.h"
|
#include <stdio.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);
|
char *read_cmdline(void);
|
||||||
|
int hyper_setup_env(struct env *envs, int num);
|
||||||
|
int hyper_find_sd(char *prefix, char *addr, char **dev);
|
||||||
int hyper_list_dir(char *path);
|
int hyper_list_dir(char *path);
|
||||||
int hyper_mkdir(char *path);
|
int hyper_mkdir(char *path);
|
||||||
int hyper_open_channel(char *channel, int mode);
|
int hyper_open_channel(char *channel, int mode);
|
||||||
int hyper_open_serial_dev(char *tty);
|
int hyper_open_serial_dev(char *tty);
|
||||||
int hyper_open_serial(char *tty);
|
|
||||||
int hyper_setfd_cloexec(int fd);
|
int hyper_setfd_cloexec(int fd);
|
||||||
int hyper_setfd_block(int fd);
|
int hyper_setfd_block(int fd);
|
||||||
int hyper_setfd_nonblock(int fd);
|
int hyper_setfd_nonblock(int fd);
|
||||||
void hyper_shutdown(struct hyper_pod *pod);
|
int hyper_socketpair(int domain, int type, int protocol, int sv[2]);
|
||||||
void hyper_kill_all(void);
|
void hyper_shutdown(void);
|
||||||
void hyper_unmount_all(void);
|
int hyper_insmod(char *module);
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user