helpers.bash 12 KB

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