helpers.bash 14 KB

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