helpers.bash 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556
  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="neighbors = [\"${nip}:7946\"]"
  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. isagent = true
  165. bind = "eth0"
  166. ${neighbors}
  167. EOF
  168. fi
  169. cat ${tomlfile}
  170. docker run \
  171. -d \
  172. --hostname=$(echo ${name} | sed s/_/-/g) \
  173. --name=${name} \
  174. --privileged \
  175. -p ${hport}:${cport} \
  176. -e _OVERLAY_HOST_MODE \
  177. -v $(pwd)/:/go/src/github.com/docker/libnetwork \
  178. -v /tmp:/tmp \
  179. -v $(pwd)/${TMPC_ROOT}:/scratch \
  180. -v /usr/local/bin/runc:/usr/local/bin/runc \
  181. -w /go/src/github.com/docker/libnetwork \
  182. mrjana/golang ./bin/dnet -d -D ${hopt} -c ${tomlfile}
  183. wait_for_dnet $(inst_id2port ${inst}) ${name}
  184. }
  185. function start_ovrouter() {
  186. local name=${1}
  187. local parent=${2}
  188. docker run \
  189. -d \
  190. --name=${name} \
  191. --net=container:${parent} \
  192. --volumes-from ${parent} \
  193. -w /go/src/github.com/docker/libnetwork \
  194. mrjana/golang ./cmd/ovrouter/ovrouter eth0
  195. }
  196. function skip_for_circleci() {
  197. if [ -n "$CIRCLECI" ]; then
  198. skip
  199. fi
  200. }
  201. function stop_dnet() {
  202. local name
  203. name=$(dnet_container_name $1 $2)
  204. rm -rf /tmp/dnet/${name} || true
  205. docker stop ${name} || true
  206. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  207. if [ -z "$CIRCLECI" ]; then
  208. docker rm -f ${name} || true
  209. fi
  210. }
  211. function dnet_cmd() {
  212. local hport
  213. hport=$1
  214. shift
  215. ./bin/dnet -H tcp://127.0.0.1:${hport} $*
  216. }
  217. function dnet_exec() {
  218. docker exec -it ${1} bash -c "$2"
  219. }
  220. function runc() {
  221. local dnet
  222. dnet=${1}
  223. shift
  224. dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
  225. dnet_exec ${dnet} "mkdir -p /var/run/netns"
  226. dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
  227. dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
  228. dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
  229. }
  230. function runc_nofail() {
  231. local dnet
  232. dnet=${1}
  233. shift
  234. dnet_exec ${dnet} "cp /var/lib/docker/network/files/${1}*/* /scratch/rootfs/etc"
  235. dnet_exec ${dnet} "mkdir -p /var/run/netns"
  236. dnet_exec ${dnet} "touch /var/run/netns/c && mount -o bind /var/run/docker/netns/${1} /var/run/netns/c"
  237. set +e
  238. dnet_exec ${dnet} "ip netns exec c unshare -fmuip --mount-proc chroot \"/scratch/rootfs\" /bin/sh -c \"/bin/mount -t proc proc /proc && ${2}\""
  239. status="$?"
  240. set -e
  241. dnet_exec ${dnet} "umount /var/run/netns/c && rm /var/run/netns/c"
  242. }
  243. function start_etcd() {
  244. local bridge_ip
  245. stop_etcd
  246. bridge_ip=$(get_docker_bridge_ip)
  247. docker run -d \
  248. --net=host \
  249. --name=dn_etcd \
  250. mrjana/etcd --listen-client-urls http://0.0.0.0:42000 \
  251. --advertise-client-urls http://${bridge_ip}:42000
  252. sleep 2
  253. }
  254. function stop_etcd() {
  255. docker stop dn_etcd || true
  256. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  257. if [ -z "$CIRCLECI" ]; then
  258. docker rm -f dn_etcd || true
  259. fi
  260. }
  261. function start_zookeeper() {
  262. stop_zookeeper
  263. docker run -d \
  264. --name=zookeeper_server \
  265. -p 2182:2181 \
  266. -h zookeeper \
  267. dnephin/docker-zookeeper:3.4.6
  268. sleep 2
  269. }
  270. function stop_zookeeper() {
  271. echo "zookeeper started"
  272. docker stop zookeeper_server || true
  273. # You cannot destroy a container in Circle CI. So do not attempt destroy in circleci
  274. if [ -z "$CIRCLECI" ]; then
  275. docker rm -f zookeeper_server || true
  276. fi
  277. }
  278. function test_overlay() {
  279. dnet_suffix=$1
  280. echo $(docker ps)
  281. start=1
  282. end=3
  283. # Setup overlay network and connect containers ot it
  284. if [ -z "${2}" -o "${2}" != "skip_add" ]; then
  285. if [ -z "${2}" -o "${2}" != "internal" ]; then
  286. dnet_cmd $(inst_id2port 1) network create -d overlay multihost
  287. else
  288. dnet_cmd $(inst_id2port 1) network create -d overlay --internal multihost
  289. fi
  290. fi
  291. for i in `seq ${start} ${end}`;
  292. do
  293. dnet_cmd $(inst_id2port $i) container create container_${i}
  294. net_connect ${i} container_${i} multihost
  295. done
  296. # Now test connectivity between all the containers using service names
  297. for i in `seq ${start} ${end}`;
  298. do
  299. if [ -z "${2}" -o "${2}" != "internal" ]; then
  300. runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) \
  301. "ping -c 1 www.google.com"
  302. else
  303. default_route=`runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) "ip route | grep default"`
  304. [ "$default_route" = "" ]
  305. fi
  306. for j in `seq ${start} ${end}`;
  307. do
  308. if [ "$i" -eq "$j" ]; then
  309. continue
  310. fi
  311. runc $(dnet_container_name $i $dnet_suffix) $(get_sbox_id ${i} container_${i}) \
  312. "ping -c 1 container_$j"
  313. done
  314. done
  315. # Setup bridge network and connect containers ot it
  316. if [ -z "${2}" -o "${2}" != "skip_add" ]; then
  317. if [ -z "${2}" -o "${2}" != "internal" ]; then
  318. dnet_cmd $(inst_id2port 1) network create -d bridge br1
  319. dnet_cmd $(inst_id2port 1) network create -d bridge br2
  320. net_connect ${start} container_${start} br1
  321. net_connect ${start} container_${start} br2
  322. # Make sure external connectivity works
  323. runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
  324. "ping -c 1 www.google.com"
  325. net_disconnect ${start} container_${start} br1
  326. net_disconnect ${start} container_${start} br2
  327. # Make sure external connectivity works
  328. runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
  329. "ping -c 1 www.google.com"
  330. dnet_cmd $(inst_id2port 1) network rm br1
  331. dnet_cmd $(inst_id2port 1) network rm br2
  332. # Disconnect from overlay network
  333. net_disconnect ${start} container_${start} multihost
  334. # Connect to overlay network again
  335. net_connect ${start} container_${start} multihost
  336. # Make sure external connectivity still works
  337. runc $(dnet_container_name ${start} $dnet_suffix) $(get_sbox_id ${start} container_${start}) \
  338. "ping -c 1 www.google.com"
  339. fi
  340. fi
  341. # Teardown the container connections and the network
  342. for i in `seq ${start} ${end}`;
  343. do
  344. net_disconnect ${i} container_${i} multihost
  345. dnet_cmd $(inst_id2port $i) container rm container_${i}
  346. done
  347. if [ -z "${2}" -o "${2}" != "skip_rm" ]; then
  348. dnet_cmd $(inst_id2port 2) network rm multihost
  349. fi
  350. }
  351. function check_etchosts() {
  352. local dnet sbid retval
  353. dnet=${1}
  354. shift
  355. sbid=${1}
  356. shift
  357. retval="true"
  358. for i in $*;
  359. do
  360. run runc ${dnet} ${sbid} "cat /etc/hosts"
  361. if [ "$status" -ne 0 ]; then
  362. retval="${output}"
  363. break
  364. fi
  365. line=$(echo ${output} | grep ${i})
  366. if [ "${line}" == "" ]; then
  367. retval="false"
  368. fi
  369. done
  370. echo ${retval}
  371. }
  372. function test_overlay_singlehost() {
  373. dnet_suffix=$1
  374. shift
  375. echo $(docker ps)
  376. start=1
  377. end=3
  378. # Setup overlay network and connect containers ot it
  379. dnet_cmd $(inst_id2port 1) network create -d overlay multihost
  380. for i in `seq ${start} ${end}`;
  381. do
  382. dnet_cmd $(inst_id2port 1) container create container_${i}
  383. net_connect 1 container_${i} multihost
  384. done
  385. # Now test connectivity between all the containers using service names
  386. for i in `seq ${start} ${end}`;
  387. do
  388. for j in `seq ${start} ${end}`;
  389. do
  390. if [ "$i" -eq "$j" ]; then
  391. continue
  392. fi
  393. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 container_${i}) \
  394. "ping -c 1 container_$j"
  395. done
  396. done
  397. # Teardown the container connections and the network
  398. for i in `seq ${start} ${end}`;
  399. do
  400. net_disconnect 1 container_${i} multihost
  401. dnet_cmd $(inst_id2port 1) container rm container_${i}
  402. done
  403. dnet_cmd $(inst_id2port 1) network rm multihost
  404. }
  405. function test_overlay_hostmode() {
  406. dnet_suffix=$1
  407. shift
  408. echo $(docker ps)
  409. start=1
  410. end=2
  411. # Setup overlay network and connect containers ot it
  412. dnet_cmd $(inst_id2port 1) network create -d overlay multihost1
  413. dnet_cmd $(inst_id2port 1) network create -d overlay multihost2
  414. dnet_cmd $(inst_id2port 1) network ls
  415. for i in `seq ${start} ${end}`;
  416. do
  417. dnet_cmd $(inst_id2port 1) container create mh1_${i}
  418. net_connect 1 mh1_${i} multihost1
  419. done
  420. for i in `seq ${start} ${end}`;
  421. do
  422. dnet_cmd $(inst_id2port 1) container create mh2_${i}
  423. net_connect 1 mh2_${i} multihost2
  424. done
  425. # Now test connectivity between all the containers using service names
  426. for i in `seq ${start} ${end}`;
  427. do
  428. for j in `seq ${start} ${end}`;
  429. do
  430. if [ "$i" -eq "$j" ]; then
  431. continue
  432. fi
  433. # Find the IP addresses of the j containers on both networks
  434. hrun runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) "nslookup mh1_$j"
  435. mh1_j_ip=$(echo ${output} | awk '{print $11}')
  436. hrun runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) "nslookup mh2_$j"
  437. mh2_j_ip=$(echo ${output} | awk '{print $11}')
  438. # Ping the j containers in the same network and ensure they are successful
  439. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) \
  440. "ping -c 1 mh1_$j"
  441. runc $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) \
  442. "ping -c 1 mh2_$j"
  443. # Try pinging j container IPs from the container in the other network and make sure that they are not successful
  444. runc_nofail $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh1_${i}) "ping -c 1 ${mh2_j_ip}"
  445. [ "${status}" -ne 0 ]
  446. runc_nofail $(dnet_container_name 1 $dnet_suffix) $(get_sbox_id 1 mh2_${i}) "ping -c 1 ${mh1_j_ip}"
  447. [ "${status}" -ne 0 ]
  448. # Try pinging the j container IPS from the host(dnet container in this case) and make syre that they are not successful
  449. hrun docker exec -it $(dnet_container_name 1 $dnet_suffix) "ping -c 1 ${mh1_j_ip}"
  450. [ "${status}" -ne 0 ]
  451. hrun docker exec -it $(dnet_container_name 1 $dnet_suffix) "ping -c 1 ${mh2_j_ip}"
  452. [ "${status}" -ne 0 ]
  453. done
  454. done
  455. # Teardown the container connections and the network
  456. for i in `seq ${start} ${end}`;
  457. do
  458. net_disconnect 1 mh1_${i} multihost1
  459. dnet_cmd $(inst_id2port 1) container rm mh1_${i}
  460. done
  461. for i in `seq ${start} ${end}`;
  462. do
  463. net_disconnect 1 mh2_${i} multihost2
  464. dnet_cmd $(inst_id2port 1) container rm mh2_${i}
  465. done
  466. dnet_cmd $(inst_id2port 1) network rm multihost1
  467. dnet_cmd $(inst_id2port 1) network rm multihost2
  468. }