elecksee 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/CHANGELOG.md +2 -0
  2. data/Gemfile +3 -0
  3. data/Gemfile.lock +18 -0
  4. data/README.md +48 -0
  5. data/bin/lxc-awesome-ephemeral +5 -0
  6. data/elecksee.gemspec +16 -0
  7. data/lib/elecksee/awesome.rb +14 -0
  8. data/lib/elecksee/lxc.rb +7 -0
  9. data/lib/elecksee/vendor/lxc/CHANGELOG.md +37 -0
  10. data/lib/elecksee/vendor/lxc/Gemfile +4 -0
  11. data/lib/elecksee/vendor/lxc/Gemfile.lock +41 -0
  12. data/lib/elecksee/vendor/lxc/README.md +112 -0
  13. data/lib/elecksee/vendor/lxc/attributes/default.rb +28 -0
  14. data/lib/elecksee/vendor/lxc/files/default/knife_lxc +228 -0
  15. data/lib/elecksee/vendor/lxc/files/default/lxc-awesome-ephemeral +495 -0
  16. data/lib/elecksee/vendor/lxc/libraries/lxc.rb +354 -0
  17. data/lib/elecksee/vendor/lxc/libraries/lxc_expanded_resources.rb +40 -0
  18. data/lib/elecksee/vendor/lxc/libraries/lxc_file_config.rb +84 -0
  19. data/lib/elecksee/vendor/lxc/libraries/monkey.rb +51 -0
  20. data/lib/elecksee/vendor/lxc/metadata.rb +12 -0
  21. data/lib/elecksee/vendor/lxc/providers/config.rb +75 -0
  22. data/lib/elecksee/vendor/lxc/providers/container.rb +318 -0
  23. data/lib/elecksee/vendor/lxc/providers/default.rb +57 -0
  24. data/lib/elecksee/vendor/lxc/providers/ephemeral.rb +40 -0
  25. data/lib/elecksee/vendor/lxc/providers/fstab.rb +30 -0
  26. data/lib/elecksee/vendor/lxc/providers/interface.rb +45 -0
  27. data/lib/elecksee/vendor/lxc/providers/service.rb +53 -0
  28. data/lib/elecksee/vendor/lxc/recipes/containers.rb +13 -0
  29. data/lib/elecksee/vendor/lxc/recipes/default.rb +58 -0
  30. data/lib/elecksee/vendor/lxc/recipes/install_dependencies.rb +15 -0
  31. data/lib/elecksee/vendor/lxc/recipes/knife.rb +37 -0
  32. data/lib/elecksee/vendor/lxc/resources/config.rb +19 -0
  33. data/lib/elecksee/vendor/lxc/resources/container.rb +54 -0
  34. data/lib/elecksee/vendor/lxc/resources/default.rb +12 -0
  35. data/lib/elecksee/vendor/lxc/resources/ephemeral.rb +13 -0
  36. data/lib/elecksee/vendor/lxc/resources/fstab.rb +12 -0
  37. data/lib/elecksee/vendor/lxc/resources/interface.rb +13 -0
  38. data/lib/elecksee/vendor/lxc/resources/service.rb +5 -0
  39. data/lib/elecksee/vendor/lxc/templates/default/client.rb.erb +13 -0
  40. data/lib/elecksee/vendor/lxc/templates/default/default-lxc.erb +3 -0
  41. data/lib/elecksee/vendor/lxc/templates/default/file_content.erb +2 -0
  42. data/lib/elecksee/vendor/lxc/templates/default/fstab.erb +5 -0
  43. data/lib/elecksee/vendor/lxc/templates/default/interface.erb +27 -0
  44. data/lib/elecksee/version.rb +6 -0
  45. data/lib/elecksee.rb +1 -0
  46. metadata +123 -0
@@ -0,0 +1,495 @@
1
+ #!/bin/bash
2
+
3
+ # (C) Copyright Canonical 2011,2012
4
+
5
+ # What lxc container to clone
6
+ LXC_BASE=""
7
+ # $2 is a path to bind mount e.g. /tmp/foo.
8
+ LXC_BIND=""
9
+ UNION="overlayfs"
10
+
11
+ usage() {
12
+ echo "usage: lxc-awesome-ephemeral [-I ipaddress] [-G gateway] [-N netmask] [-D size] [-z rdir] [-U uniontype] [-d|--daemon] [-h] [-b bdir] [-u user] [-S key] -o orig -- [COMMAND [ARGS...]]"
13
+ }
14
+
15
+ help() {
16
+ usage
17
+ echo
18
+ echo "Runs an ephemeral (one-off) container"
19
+ echo
20
+ echo "Options:"
21
+ echo "orig : name of the original container"
22
+ echo "bdir : directory to bind mount into container"
23
+ echo "user : the user to connect to the container as"
24
+ echo "key : the path to the SSH key to use to connect"
25
+ echo "size : size of virtual device in M"
26
+ echo "rdir : host directory to store rootfs overlay"
27
+ echo "ipaddress : static ipv4 to use instead of dhcp"
28
+ echo "-d : run in the background"
29
+ echo "-U : type of union (aufs or overlayfs)"
30
+ echo " Default is overlayfs"
31
+ echo "-D : block device for rootfs overlay"
32
+ echo "-z : directory to use for rootfs overlay"
33
+ echo "-I : ip address to use"
34
+ echo "-G : gateway to use"
35
+ echo "-N : netmask to use"
36
+ echo
37
+ echo "if a COMMAND is given, then the container will run only as long"
38
+ echo "as the command runs. If no COMMAND is given, this command will"
39
+ echo "wait until the container is shut down"
40
+ }
41
+
42
+ shortoptions='hb:o:u:D:z:I:G:N:S:dU:'
43
+ longoptions='help,orig:,bdir:,user:,device:,directory:,ipaddress:,gateway:,netmask:,ssh-key:,daemon,union:'
44
+
45
+ LXC_RUNNING=0
46
+ LXC_MOUNTED=0
47
+ DAEMON=0
48
+
49
+ cleanup_dirs()
50
+ {
51
+ if [ $LXC_DIR = '/' ]; then
52
+ echo "ABORT ABORT ABORT -> LXC Directory set to root. Will. Not. Delete!"
53
+ exit 42
54
+ fi
55
+ # echo "umounting ephemeral_bind_dir $EPHEMERAL_BIND_DIR" >&2
56
+ sudo umount $EPHEMERAL_BIND_DIR > /dev/null 2>&1
57
+ # echo "umounting lxc_dir $LXC_DIR" >&2
58
+ sudo umount $LXC_DIR/rootfs > /dev/null 2>&1
59
+ # echo "umounting overlay" >&2
60
+ if [ ! $HOST_OVERLAY_DIRECTORY ]; then
61
+ sudo umount $OVERLAY_DIR > /dev/null 2>&1
62
+ fi
63
+ # remove all contents of the content dir
64
+ sudo rm -rf $LXC_DIR
65
+
66
+ # echo "rming overlay dir $OVERLAY_DIR" >&2
67
+ if [ $HOST_OVERLAY_DIRECTORY ]; then
68
+ if [ $HOST_OVERLAY_DIRECTORY = '/' ]; then
69
+ echo "ABORT ABORT ABORT -> Overlay Directory set to root. Will. Not. Delete!"
70
+ exit 42
71
+ fi
72
+
73
+ if [ $VIRT_DIR ]; then
74
+ sudo umount $VIRT_MNT > /dev/null 2>&1
75
+ sudo rmdir $VIRT_MNT > /dev/null 2>&1
76
+ sudo rm -f $VIRT_DEV
77
+ fi
78
+ sudo rm -rf $HOST_OVERLAY_DIRECTORY
79
+ else
80
+ if [ $OVERLAY_DIR = '/' ]; then
81
+ echo "ABORT ABORT ABORT -> Overlay Directory set to root. Will. Not. Delete!"
82
+ exit 42
83
+ fi
84
+ sudo rm -rf $OVERLAY_DIR
85
+ fi
86
+ }
87
+
88
+ create_virt_device() {
89
+ echo "Creating ephemeral virtual device for rootfs (${OVERLAY_DEVICE}M)"
90
+ VIRT_DIR="/tmp/lxc-virt-devs"
91
+ VIRT_IMG_DIR="${VIRT_DIR}/imgs"
92
+ VIRT_MNT_DIR="${VIRT_DIR}/mnt"
93
+ VIRT_DEV="${VIRT_IMG_DIR}/${LXC_NAME}"
94
+ VIRT_MNT="${VIRT_MNT_DIR}/${LXC_NAME}"
95
+ sudo mkdir -p $VIRT_DIR
96
+ sudo mkdir -p $VIRT_IMG_DIR
97
+ sudo mkdir -p $VIRT_MNT
98
+ # Create empty disk
99
+ dd if=/dev/zero of=$VIRT_DEV bs=1k seek=${OVERLAY_DEVICE}k count=1 > /dev/null
100
+ # format device
101
+ echo "y" | mkfs -t ext4 $VIRT_DEV > /dev/null
102
+ # mount loopback
103
+ mount -o loop $VIRT_DEV $VIRT_MNT
104
+ HOST_OVERLAY_DIRECTORY=$VIRT_MNT
105
+ }
106
+
107
+ cleanup() {
108
+ if [ $LXC_RUNNING -eq 1 ]; then
109
+ sudo lxc-stop -n $LXC_NAME
110
+ fi
111
+ if [ $LXC_MOUNTED -eq 1 ]; then
112
+ cleanup_dirs
113
+ fi
114
+ exit 1
115
+ }
116
+
117
+ do_mount() {
118
+ lower=$1
119
+ if [ $OVERLAY_DEVICE ]; then
120
+ create_virt_device
121
+ upper=$HOST_OVERLAY_DIRECTORY
122
+ echo "Using local block device for overlay mounted at: ${HOST_OVERLAY_DIRECTORY}"
123
+ elif [ $HOST_OVERLAY_DIRECTORY ]; then
124
+ mkdir -p $HOST_OVERLAY_DIRECTORY
125
+ HOST_OVERLAY_DIRECTORY=`mktemp -d --tmpdir=$HOST_OVERLAY_DIRECTORY $LXC_BASE-temp-XXXXXXX`
126
+ upper=$HOST_OVERLAY_DIRECTORY
127
+ echo "Using local directory for overlay: ${HOST_OVERLAY_DIRECTORY}"
128
+ else
129
+ upper=$2
130
+ fi
131
+ target=$3
132
+ if [ $UNION = "aufs" ]; then
133
+ sudo mount -t aufs -o br=${upper}=rw:${lower}=ro,noplink none ${target}
134
+ else
135
+ sudo mount -t overlayfs -oupperdir=${upper},lowerdir=${lower} none ${target}
136
+ fi
137
+ }
138
+
139
+ trap cleanup SIGTERM SIGINT SIGQUIT
140
+
141
+ getopt=$(getopt -o $shortoptions --longoptions $longoptions -- "$@")
142
+ if [ $? != 0 ]; then
143
+ usage
144
+ exit 1;
145
+ fi
146
+
147
+ eval set -- "$getopt"
148
+
149
+ while true; do
150
+ case "$1" in
151
+ -h|--help)
152
+ help
153
+ exit 1
154
+ ;;
155
+ -o|--orig)
156
+ shift
157
+ LXC_BASE=$1
158
+ shift
159
+ ;;
160
+ -D|--device)
161
+ shift
162
+ OVERLAY_DEVICE=$1
163
+ shift
164
+ ;;
165
+ -z|--directory)
166
+ shift
167
+ HOST_OVERLAY_DIRECTORY=$1
168
+ shift
169
+ ;;
170
+ -b|--bdir)
171
+ shift
172
+ LXC_BIND=$1
173
+ shift
174
+ ;;
175
+ -u|--user)
176
+ shift
177
+ LXC_USER=$1
178
+ shift
179
+ ;;
180
+ -S|--ssh-key)
181
+ shift
182
+ LXC_KEY="-i $1"
183
+ shift
184
+ ;;
185
+ -d|--detach)
186
+ DAEMON=1
187
+ shift
188
+ ;;
189
+ -I|--ipaddress)
190
+ shift
191
+ CUSTOM_IPADDRESS=$1
192
+ shift
193
+ ;;
194
+ -G|--gateway)
195
+ shift
196
+ CUSTOM_GATEWAY=$1
197
+ shift
198
+ ;;
199
+ -N|--netmask)
200
+ shift
201
+ CUSTOM_NETMASK=$1
202
+ shift
203
+ ;;
204
+ -U|--union)
205
+ shift
206
+ UNION=$1
207
+ shift
208
+ ;;
209
+ --)
210
+ shift
211
+ break;;
212
+ *)
213
+ echo $1
214
+ usage
215
+ exit 1
216
+ ;;
217
+ esac
218
+ done
219
+
220
+ COMMAND=$@
221
+ COMMAND_LENGTH=$#
222
+ LXC_USER=${LXC_USER:-`id -un`}
223
+
224
+ # validation
225
+
226
+ if [ -z $LXC_BASE ]; then
227
+ echo "original container must be specified"
228
+ usage
229
+ exit 1
230
+ fi
231
+ if [ ! -d /var/lib/lxc/$LXC_BASE ] ; then
232
+ echo "no such lxc container $LXC_BASE"
233
+ exit 1
234
+ fi
235
+
236
+ if [ "$UNION" != "overlayfs" -a "$UNION" != "aufs" ]; then
237
+ echo "Invalid option for union: choose overlayfs or aufs."
238
+ exit 1
239
+ fi
240
+
241
+ setup_container()
242
+ {
243
+ echo "Setting up ephemeral container..."
244
+ if [ $HOST_OVERLAY_DIRECTORY ]; then
245
+ echo " -- Using local directory for overlay: ${HOST_OVERLAY_DIRECTORY}"
246
+ elif [ $OVERLAY_DEVICE ]; then
247
+ echo " -- Using overlay virtual block device"
248
+ else
249
+ OVERLAY_DIR=`mktemp -d /tmp/lxc-lp-XXXXXXX`
250
+ sudo mount -t tmpfs none $OVERLAY_DIR
251
+ fi
252
+ LXC_DIR=`sudo mktemp -d --tmpdir=/var/lib/lxc $LXC_BASE-temp-XXXXXXX`
253
+ sudo chmod 755 ${LXC_DIR}
254
+ LXC_NAME=`basename $LXC_DIR`
255
+ sudo mkdir ${LXC_DIR}/rootfs
256
+ do_mount "/var/lib/lxc/$LXC_BASE/rootfs" "${OVERLAY_DIR}" ${LXC_DIR}/rootfs
257
+ EPHEMERAL_BIND_DIR=$LXC_DIR/ephemeralbind
258
+ sudo mkdir $EPHEMERAL_BIND_DIR
259
+ sudo mount -t tmpfs none $EPHEMERAL_BIND_DIR
260
+ LXC_MOUNTED=1
261
+ {
262
+ d1=/var/lib/lxc/${LXC_BASE}
263
+ for f in ${d1}/*; do
264
+ if [ -f $f ]; then
265
+ sudo cp $f $LXC_DIR/
266
+ fi
267
+ done
268
+ }
269
+
270
+ # Update the ephemeral lxc's configuration to reflect the new container name.
271
+ # Check all the places known distros keep hostnames.
272
+ # FIXME: should we sanity check the hostname to make sure it contains no bad chars?
273
+ for file in $LXC_DIR/fstab $LXC_DIR/config \
274
+ $LXC_DIR/rootfs/etc/hostname \
275
+ $LXC_DIR/rootfs/etc/hosts \
276
+ $LXC_DIR/rootfs/etc/sysconfig/network \
277
+ $LXC_DIR/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
278
+ do
279
+ if test -f "$file"
280
+ then
281
+ sudo sed -i -e "s/$LXC_BASE/$LXC_NAME/" $file
282
+ fi
283
+ done
284
+
285
+ if [ -e $LXC_DIR/rootfs/etc/redhat-release ]; then
286
+ DISTRO="EL"
287
+ else
288
+ DISTRO="DEBIAN"
289
+ fi
290
+
291
+ # special tweaks for the centos family of distributions
292
+ if [ $DISTRO = "EL" ] ; then
293
+ cat <<EOF > $LXC_DIR/rootfs/etc/sysconfig/network
294
+ NETWORKING=yes
295
+ HOSTNAME=$LXC_NAME
296
+ EOF
297
+ echo "hostname $LXC_NAME" >> $LXC_DIR/rootfs/etc/rc.local
298
+ fi
299
+
300
+ # Update the fstab to have all bind mounts be ephemeral.
301
+ sudo cp $LXC_DIR/fstab $LXC_DIR/fstab.old
302
+ while read line; do
303
+ # Pull out the second field of the current line of fstab info
304
+ path=`echo -n $line | awk '{print $2}'`
305
+ # If LXC_BIND is not set, or the mount destination of this line is not
306
+ # LXC_BIND...
307
+ if [ -n "$path" ] && [ -z "$LXC_BIND" -o "`readlink -f $path`" != "`readlink -f $LXC_DIR/rootfs$LXC_BIND`" ];
308
+ then
309
+ # ...then we should write some form of this line.
310
+ # If this line is a bind...
311
+ if [ `echo -n $line | awk '{print $4}'` = "bind" ]; then
312
+ # ...we should rewrite it as an overlay.
313
+ source=`echo -n $line | awk '{print $1}'`
314
+ upperdir=$EPHEMERAL_BIND_DIR$source
315
+ sudo mkdir -p $upperdir
316
+ sudo chown `sudo stat -c '%U.%G' $source` $upperdir
317
+ if [ $UNION = "overlayfs" ]; then
318
+ echo "none $path overlayfs upperdir=$upperdir,lowerdir=$source 0 0";
319
+ else
320
+ echo "none $path aufs br=${upperdir}=rw:${lowerdir}=ro,noplink 0 0";
321
+ fi
322
+ else
323
+ # Otherwise, we can pass it through unchanged.
324
+ echo "$line";
325
+ fi
326
+ fi
327
+ done < $LXC_DIR/fstab.old | sudo tee $LXC_DIR/fstab >/dev/null
328
+
329
+ # If LXC_BIND is defined, add it to fstab.
330
+ if [ -n "$LXC_BIND" ]; then
331
+ sudo mkdir -p $LXC_DIR/rootfs$LXC_BIND
332
+ echo "$LXC_BIND $LXC_DIR/rootfs$LXC_BIND none bind 0 0" | sudo tee -a $LXC_DIR/fstab >/dev/null
333
+ fi
334
+
335
+ # update the ephemeral container's MAC address (lifted from lxc-clone)
336
+ c=$LXC_DIR/config
337
+ # change hwaddrs
338
+ sudo mv ${c} ${c}.old
339
+ (
340
+ while read line; do
341
+ if [ "${line:0:18}" = "lxc.network.hwaddr" ]; then
342
+ echo "lxc.network.hwaddr= 00:16:3e:$(openssl rand -hex 3| sed 's/\(..\)/\1:/g; s/.$//')"
343
+ else
344
+ echo "$line"
345
+ fi
346
+ done
347
+ ) < ${c}.old | sudo tee ${c} >/dev/null
348
+ sudo rm -f ${c}.old
349
+
350
+ if [ $CUSTOM_IPADDRESS ]; then
351
+ if [ -z $CUSTOM_GATEWAY ]; then
352
+ CUSTOM_GATEWAY=`echo $CUSTOM_IPADDRESS | sed 's/[0-9]\+$/1/'`
353
+ fi
354
+ if [ -z $CUSTOM_NETMASK ]; then
355
+ CUSTOM_NETMASK='255.255.255.0'
356
+ fi
357
+ write_custom_networking
358
+ fi
359
+ }
360
+
361
+ get_ip()
362
+ {
363
+ # Get init's PID
364
+ PID=$(sudo lxc-info -n $1 -p | awk '{print $2}')
365
+ [ "$PID" = "-1" ] && return 1
366
+
367
+ # Get some unique path
368
+ DST=$(sudo mktemp -u --tmpdir=/run/netns/)
369
+ NAME=$(basename $DST)
370
+
371
+ # Prepare the /run/netns entry for "ip netns"
372
+ sudo mkdir -p /run/netns
373
+ sudo ln -s /proc/$PID/ns/net $DST
374
+
375
+ # Grab all the public globally routed IPv4 and IPv6 addresses
376
+ (sudo ip netns exec $NAME ip -4 addr show scope global && \
377
+ [ sudo ip netns exec $NAME ip -6 addr show scope global) | grep inet | while read line; do
378
+ ip=$(echo $line | awk '{print $2}' | cut -d '/' -f1)
379
+ echo "$ip"
380
+ done
381
+
382
+ sudo rm $DST
383
+ }
384
+
385
+ start_container()
386
+ {
387
+ echo "Starting up the container..."
388
+ sudo lxc-start -n $LXC_NAME -d
389
+ sudo lxc-wait -s RUNNING -n $LXC_NAME
390
+ LXC_RUNNING=1
391
+
392
+ if [ $COMMAND_LENGTH -gt 0 ]; then
393
+ # When lxc-attach support arrives in the kernel, we can switch to
394
+ # that.
395
+ # Meanwhile, we use get_ip to wait for container's network to be up
396
+ # and to obtain the ip address, then we can ssh to the lxc.
397
+ TRIES=60
398
+ FAILED=1
399
+
400
+ # Repeatedly try to connect over SSH until we either succeed
401
+ # or time out.
402
+ for i in $(seq 1 $TRIES); do
403
+ # We call get_ip inside the loop to ensure the correct ip
404
+ # is retrieved even in the case the DHCP ip assignment
405
+ # changes during the process.
406
+ IP_ADDRESS=$(get_ip $LXC_NAME)
407
+ if [ -z "$IP_ADDRESS" ]; then
408
+ sleep 1
409
+ continue
410
+ fi
411
+
412
+ # Iterate through all the addresses (if multiple)
413
+ for ip in $IP_ADDRESS; do
414
+ ssh -n -o StrictHostKeyChecking=no \
415
+ -o UserKnownHostsFile=/dev/null \
416
+ $LXC_KEY $LXC_USER@$IP_ADDRESS -- "$COMMAND"
417
+ SSH_RET=$?
418
+ if [ ! 255 -eq $SSH_RET ]; then
419
+ # If ssh returns 255 then its connection failed.
420
+ # Anything else is either success (status 0) or a
421
+ # failure from whatever we ran over the SSH connection.
422
+ # In those cases we want to stop looping, so we break
423
+ # here
424
+ return $SSH_RET
425
+ fi
426
+ done
427
+ sleep 1
428
+ done
429
+
430
+ echo "could not get IP address - aborting." >&2
431
+ return 255
432
+ else
433
+ sudo lxc-wait -n $LXC_NAME -s RUNNING
434
+ echo "$LXC_NAME is running"
435
+ echo "You connect with the command:"
436
+ echo " sudo lxc-console -n $LXC_NAME"
437
+ sudo lxc-wait -n $LXC_NAME -s STOPPED
438
+ fi
439
+ }
440
+
441
+ write_custom_networking()
442
+ {
443
+ if [ $DISTRO = "EL" ] ; then
444
+ cat <<EOF > $LXC_DIR/rootfs/etc/sysconfig/network-scripts/ifcfg-eth0
445
+ DEVICE=eth0
446
+ BOOTPROTO=static
447
+ NETMASK=$CUSTOM_NETMASK
448
+ IPADDR=$CUSTOM_IPADDRESS
449
+ ONBOOT=yes
450
+ TYPE=Ethernet
451
+ USERCTL=yes
452
+ PEERDNS=yes
453
+ IPV6INIT=no
454
+ GATEWAY=$CUSTOM_GATEWAY
455
+ EOF
456
+ else
457
+ cat <<EOF > $LXC_DIR/rootfs/etc/network/interfaces
458
+ auto lo
459
+ iface lo inet loopback
460
+ auto eth0
461
+ iface eth0 inet static
462
+ address $CUSTOM_IPADDRESS
463
+ netmask $CUSTOM_NETMASK
464
+ gateway $CUSTOM_GATEWAY
465
+ EOF
466
+ fi
467
+ }
468
+
469
+ stop_container()
470
+ {
471
+ echo "Stopping lxc" >&2
472
+ sudo lxc-stop -n $LXC_NAME
473
+ sleep 2
474
+ LXC_RUNNING=0
475
+ cleanup_dirs
476
+ }
477
+
478
+ handle_container()
479
+ {
480
+ setup_container
481
+ start_container
482
+ RET=$?
483
+ stop_container
484
+ if [ $DAEMON -eq 1 ]; then
485
+ cleanup
486
+ fi
487
+ exit $RET
488
+ }
489
+
490
+ if [ $DAEMON -eq 1 ]; then
491
+ handle_container &
492
+ exit 0
493
+ fi
494
+
495
+ handle_container