helpers.bash 14 KB

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