helpers.bash 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518
  1. function get_docker_bridge_ip() {
  2. echo $(docker run --rm -it busybox ip route show | grep default | cut -d" " -f3)
  3. }
  4. function inst_id2port() {
  5. echo $((41000+${1}-1))
  6. }
  7. function dnet_container_name() {
  8. echo dnet-$1-$2
  9. }
  10. function dnet_container_ip() {
  11. docker inspect --format '{{.NetworkSettings.IPAddress}}' dnet-$1-$2
  12. }
  13. function get_sbox_id() {
  14. local line
  15. line=$(dnet_cmd $(inst_id2port ${1}) service ls | grep ${2})
  16. echo ${line} | cut -d" " -f5
  17. }
  18. function net_connect() {
  19. local al gl
  20. if [ -n "$4" ]; then
  21. if [ "${4}" != ":" ]; then
  22. al="--alias=${4}"
  23. fi
  24. fi
  25. if [ -n "$5" ]; then
  26. gl="--alias=${5}"
  27. fi
  28. dnet_cmd $(inst_id2port ${1}) service publish $gl ${2}.${3}
  29. dnet_cmd $(inst_id2port ${1}) service attach $al ${2} ${2}.${3}
  30. }
  31. function net_disconnect() {
  32. dnet_cmd $(inst_id2port ${1}) service detach ${2} ${2}.${3}
  33. dnet_cmd $(inst_id2port ${1}) service unpublish ${2}.${3}
  34. }
  35. function start_consul() {
  36. stop_consul
  37. docker run -d \
  38. --name=pr_consul \
  39. -p 8500:8500 \
  40. -p 8300-8302:8300-8302/tcp \
  41. -p 8300-8302:8300-8302/udp \
  42. -h consul \
  43. progrium/consul -server -bootstrap
  44. sleep 2
  45. }
  46. function stop_consul() {
  47. echo "consul started"
  48. docker rm -f pr_consul || true
  49. }
  50. hrun() {
  51. local e E T oldIFS
  52. [[ ! "$-" =~ e ]] || e=1
  53. [[ ! "$-" =~ E ]] || E=1
  54. [[ ! "$-" =~ T ]] || T=1
  55. set +e
  56. set +E
  57. set +T
  58. output="$("$@" 2>&1)"
  59. status="$?"
  60. oldIFS=$IFS
  61. IFS=$'\n' lines=($output)
  62. [ -z "$e" ] || set -e
  63. [ -z "$E" ] || set -E
  64. [ -z "$T" ] || set -T
  65. IFS=$oldIFS
  66. }
  67. function wait_for_dnet() {
  68. local hport
  69. hport=$1
  70. echo "waiting on dnet to come up ..."
  71. for i in `seq 1 10`;
  72. do
  73. hrun ./bin/dnet -H tcp://127.0.0.1:${hport} network ls
  74. echo ${output}
  75. if [ "$status" -eq 0 ]; then
  76. return
  77. fi
  78. if [[ "${lines[1]}" =~ .*EOF.* ]]
  79. then
  80. docker logs ${2}
  81. fi
  82. echo "still waiting after ${i} seconds"
  83. sleep 1
  84. done
  85. }
  86. function parse_discovery_str() {
  87. local d provider address
  88. discovery=$1
  89. provider=$(echo ${discovery} | cut -d":" -f1)
  90. address=$(echo ${discovery} | cut -d":" -f2):$(echo ${discovery} | cut -d":" -f3)
  91. address=${address:2}
  92. echo "${discovery} ${provider} ${address}"
  93. }
  94. function start_dnet() {
  95. local inst suffix name hport cport hopt store bridge_ip labels tomlfile nip
  96. local discovery provider address
  97. inst=$1
  98. shift
  99. suffix=$1
  100. shift
  101. store=$(echo $suffix | cut -d":" -f1)
  102. nip=$(echo $suffix | cut -s -d":" -f2)
  103. stop_dnet ${inst} ${store}
  104. name=$(dnet_container_name ${inst} ${store})
  105. hport=$((41000+${inst}-1))
  106. cport=2385
  107. hopt=""
  108. while [ -n "$1" ]
  109. do
  110. if [[ "$1" =~ ^[0-9]+$ ]]
  111. then
  112. hport=$1
  113. cport=$1
  114. hopt="-H tcp://0.0.0.0:${cport}"
  115. else
  116. store=$1
  117. fi
  118. shift
  119. done
  120. bridge_ip=$(get_docker_bridge_ip)
  121. echo "start_dnet parsed values: " ${inst} ${suffix} ${name} ${hport} ${cport} ${hopt} ${store}
  122. mkdir -p /tmp/dnet/${name}
  123. tomlfile="/tmp/dnet/${name}/libnetwork.toml"
  124. # Try discovery URLs with or without path
  125. neigh_ip=""
  126. neighbors=""
  127. if [ "$store" = "etcd" ]; then
  128. read discovery provider address < <(parse_discovery_str etcd://${bridge_ip}:42000/custom_prefix)
  129. elif [ "$store" = "consul" ]; then
  130. read discovery provider address < <(parse_discovery_str consul://${bridge_ip}:8500/custom_prefix)
  131. else
  132. if [ "$nip" != "" ]; then
  133. neighbors=${nip}
  134. fi
  135. discovery=""
  136. provider=""
  137. address=""
  138. fi
  139. if [ "$discovery" != "" ]; then
  140. cat > ${tomlfile} <<EOF
  141. title = "LibNetwork Configuration file for ${name}"
  142. [daemon]
  143. debug = false
  144. [cluster]
  145. discovery = "${discovery}"
  146. Heartbeat = 10
  147. [scopes]
  148. [scopes.global]
  149. [scopes.global.client]
  150. provider = "${provider}"
  151. address = "${address}"
  152. EOF
  153. else
  154. cat > ${tomlfile} <<EOF
  155. title = "LibNetwork Configuration file for ${name}"
  156. [daemon]
  157. debug = false
  158. [orchestration]
  159. agent = true
  160. bind = "eth0"
  161. peer = "${neighbors}"
  162. EOF
  163. fi
  164. cat ${tomlfile}
  165. docker run \
  166. -d \
  167. --hostname=$(echo ${name} | sed s/_/-/g) \
  168. --name=${name} \
  169. --privileged \
  170. -p ${hport}:${cport} \
  171. -e _OVERLAY_HOST_MODE \
  172. -v $(pwd)/:/go/src/github.com/docker/libnetwork \
  173. -v /tmp:/tmp \
  174. -v $(pwd)/${TMPC_ROOT}:/scratch \
  175. -v /usr/local/bin/runc:/usr/local/bin/runc \
  176. -w /go/src/github.com/docker/libnetwork \
  177. mrjana/golang ./bin/dnet -d -D ${hopt} -c ${tomlfile}
  178. wait_for_dnet $(inst_id2port ${inst}) ${name}
  179. }
  180. function start_ovrouter() {
  181. local name=${1}
  182. local parent=${2}
  183. docker run \
  184. -d \
  185. --name=${name} \
  186. --net=container:${parent} \
  187. --volumes-from ${parent} \
  188. -w /go/src/github.com/docker/libnetwork \
  189. mrjana/golang ./cmd/ovrouter/ovrouter eth0
  190. }
  191. function stop_dnet() {
  192. local name
  193. name=$(dnet_container_name $1 $2)
  194. rm -rf /tmp/dnet/${name} || true
  195. docker rm -f ${name} || true
  196. }
  197. function dnet_cmd() {
  198. local hport
  199. hport=$1
  200. shift
  201. ./bin/dnet -H tcp://127.0.0.1:${hport} $*
  202. }
  203. function dnet_exec() {
  204. docker exec -it ${1} bash -c "trap \"echo SIGHUP\" SIGHUP; $2"
  205. }
  206. function runc() {
  207. local dnet
  208. dnet=${1}
  209. shift
  210. dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
  211. dnet_exec ${dnet} "mkdir -p /var/run/netns"
  212. dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
  213. dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
  214. dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
  215. }
  216. function runc_nofail() {
  217. local dnet
  218. dnet=${1}
  219. shift
  220. dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
  221. dnet_exec ${dnet} "mkdir -p /var/run/netns"
  222. dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
  223. set +e
  224. dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
  225. status="$?"
  226. set -e
  227. dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
  228. }
  229. function start_etcd() {
  230. local bridge_ip
  231. stop_etcd
  232. bridge_ip=$(get_docker_bridge_ip)
  233. docker run -d \
  234. --net=host \
  235. --name=dn_etcd \
  236. mrjana/etcd --listen-client-urls http://0.0.0.0:42000 \
  237. --advertise-client-urls http://${bridge_ip}:42000
  238. sleep 2
  239. }
  240. function stop_etcd() {
  241. docker rm -f dn_etcd || true
  242. }
  243. function test_overlay() {
  244. dnet_suffix=$1
  245. echo $(docker ps)
  246. start=1
  247. end=3
  248. # Setup overlay network and connect containers to it
  249. if [ -z "${2}" -o "${2}" != "skip_add" ]; then
  250. if [ -z "${2}" -o "${2}" != "internal" ]; then
  251. dnet_cmd $(inst_id2port 1) network create -d overlay multihost
  252. else
  253. dnet_cmd $(inst_id2port 1) network create -d overlay --internal multihost
  254. fi
  255. fi
  256. for i in `seq ${start} ${end}`;
  257. do
  258. dnet_cmd $(inst_id2port $i) container create container_${i}
  259. net_connect ${i} container_${i} multihost
  260. done
  261. # Now test connectivity between all the containers using service names
  262. for i in `seq ${start} ${end}`;
  263. do
  264. if [ -z "${2}" -o "${2}" != "internal" ]; then
  265. runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) \
  266. "ping -c 1 www.google.com"
  267. else
  268. default_route=`runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) "ip route | grep default"`
  269. [ "$default_route" = "" ]
  270. fi
  271. for j in `seq ${start} ${end}`;
  272. do
  273. if [ "$i" -eq "$j" ]; then
  274. continue
  275. fi
  276. runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) \
  277. "ping -c 1 container_$j"
  278. done
  279. done
  280. # Setup bridge network and connect containers to it
  281. if [ -z "${2}" -o "${2}" != "skip_add" ]; then
  282. if [ -z "${2}" -o "${2}" != "internal" ]; then
  283. dnet_cmd $(inst_id2port 1) network create -d bridge br1
  284. dnet_cmd $(inst_id2port 1) network create -d bridge br2
  285. net_connect ${start} container_${start} br1
  286. net_connect ${start} container_${start} br2
  287. # Make sure external connectivity works
  288. runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
  289. "ping -c 1 www.google.com"
  290. net_disconnect ${start} container_${start} br1
  291. net_disconnect ${start} container_${start} br2
  292. # Make sure external connectivity works
  293. runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
  294. "ping -c 1 www.google.com"
  295. dnet_cmd $(inst_id2port 1) network rm br1
  296. dnet_cmd $(inst_id2port 1) network rm br2
  297. # Disconnect from overlay network
  298. net_disconnect ${start} container_${start} multihost
  299. # Connect to overlay network again
  300. net_connect ${start} container_${start} multihost
  301. # Make sure external connectivity still works
  302. runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
  303. "ping -c 1 www.google.com"
  304. fi
  305. fi
  306. # Teardown the container connections and the network
  307. for i in `seq ${start} ${end}`;
  308. do
  309. net_disconnect ${i} container_${i} multihost
  310. dnet_cmd $(inst_id2port $i) container rm container_${i}
  311. done
  312. if [ -z "${2}" -o "${2}" != "skip_rm" ]; then
  313. dnet_cmd $(inst_id2port 2) network rm multihost
  314. fi
  315. }
  316. function check_etchosts() {
  317. local dnet sbid retval
  318. dnet=${1}
  319. shift
  320. sbid=${1}
  321. shift
  322. retval="true"
  323. for i in $*;
  324. do
  325. run runc ${dnet} ${sbid} "cat /etc/hosts"
  326. if [ "$status" -ne 0 ]; then
  327. retval="${output}"
  328. break
  329. fi
  330. line=$(echo ${output} | grep ${i})
  331. if [ "${line}" == "" ]; then
  332. retval="false"
  333. fi
  334. done
  335. echo ${retval}
  336. }
  337. function test_overlay_singlehost() {
  338. dnet_suffix=$1
  339. shift
  340. echo $(docker ps)
  341. start=1
  342. end=3
  343. # Setup overlay network and connect containers to it
  344. dnet_cmd $(inst_id2port 1) network create -d overlay multihost
  345. for i in `seq ${start} ${end}`;
  346. do
  347. dnet_cmd $(inst_id2port 1) container create container_${i}
  348. net_connect 1 container_${i} multihost
  349. done
  350. # Now test connectivity between all the containers using service names
  351. for i in `seq ${start} ${end}`;
  352. do
  353. for j in `seq ${start} ${end}`;
  354. do
  355. if [ "$i" -eq "$j" ]; then
  356. continue
  357. fi
  358. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 container_${i}) \
  359. "ping -c 1 container_$j"
  360. done
  361. done
  362. # Teardown the container connections and the network
  363. for i in `seq ${start} ${end}`;
  364. do
  365. net_disconnect 1 container_${i} multihost
  366. dnet_cmd $(inst_id2port 1) container rm container_${i}
  367. done
  368. dnet_cmd $(inst_id2port 1) network rm multihost
  369. }
  370. function test_overlay_hostmode() {
  371. dnet_suffix=$1
  372. shift
  373. echo $(docker ps)
  374. start=1
  375. end=2
  376. # Setup overlay network and connect containers to it
  377. dnet_cmd $(inst_id2port 1) network create -d overlay multihost1
  378. dnet_cmd $(inst_id2port 1) network create -d overlay multihost2
  379. dnet_cmd $(inst_id2port 1) network ls
  380. for i in `seq ${start} ${end}`;
  381. do
  382. dnet_cmd $(inst_id2port 1) container create mh1_${i}
  383. net_connect 1 mh1_${i} multihost1
  384. done
  385. for i in `seq ${start} ${end}`;
  386. do
  387. dnet_cmd $(inst_id2port 1) container create mh2_${i}
  388. net_connect 1 mh2_${i} multihost2
  389. done
  390. # Now test connectivity between all the containers using service names
  391. for i in `seq ${start} ${end}`;
  392. do
  393. for j in `seq ${start} ${end}`;
  394. do
  395. if [ "$i" -eq "$j" ]; then
  396. continue
  397. fi
  398. # Find the IP addresses of the j containers on both networks
  399. hrun runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) "nslookup mh1_$j"
  400. mh1_j_ip=$(echo ${output} | awk '{print $11}')
  401. hrun runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) "nslookup mh2_$j"
  402. mh2_j_ip=$(echo ${output} | awk '{print $11}')
  403. # Ping the j containers in the same network and ensure they are successful
  404. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) \
  405. "ping -c 1 mh1_$j"
  406. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) \
  407. "ping -c 1 mh2_$j"
  408. # Try pinging j container IPs from the container in the other network and make sure that they are not successful
  409. runc_nofail $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) "ping -c 1 ${mh2_j_ip}"
  410. [ "${status}" -ne 0 ]
  411. runc_nofail $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) "ping -c 1 ${mh1_j_ip}"
  412. [ "${status}" -ne 0 ]
  413. # Try pinging the j container IPS from the host(dnet container in this case) and make syre that they are not successful
  414. hrun docker exec -it $(dnet_container_name 1 $dnet_suffix) "ping -c 1 ${mh1_j_ip}"
  415. [ "${status}" -ne 0 ]
  416. hrun docker exec -it $(dnet_container_name 1 $dnet_suffix) "ping -c 1 ${mh2_j_ip}"
  417. [ "${status}" -ne 0 ]
  418. done
  419. done
  420. # Teardown the container connections and the network
  421. for i in `seq ${start} ${end}`;
  422. do
  423. net_disconnect 1 mh1_${i} multihost1
  424. dnet_cmd $(inst_id2port 1) container rm mh1_${i}
  425. done
  426. for i in `seq ${start} ${end}`;
  427. do
  428. net_disconnect 1 mh2_${i} multihost2
  429. dnet_cmd $(inst_id2port 1) container rm mh2_${i}
  430. done
  431. dnet_cmd $(inst_id2port 1) network rm multihost1
  432. dnet_cmd $(inst_id2port 1) network rm multihost2
  433. }