This repository has been archived on 2026-05-18. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
disco/README.md

378 lines
16 KiB
Markdown
Raw Normal View History

2012-08-05 16:10:42 -07:00
disco
=====
Dead Simple COnfiguration management and continuous integration for linux like systems
DISCO uses simple, proven technologies to achieve the goal of configuration management.
* rsync for data transfer from master to client
* bash for scripts and templating
* unionfs and restricted bash for noop operations
* plaintext files in a structured directory tree for node classification and configuration
2012-08-05 22:04:23 -04:00
DISCO is in the very early alpha stages of development. At this point, I am fairly confident
that it won't destroy the system you run it on, but I still only run it on disposable virtual
machines until it reaches a higher level of maturity.
2012-08-05 22:04:23 -04:00
Server Side Setup
=====
The only server side setup required for DISCO is to setup an rsyncd and sshd server. This is outside
the purview of this README.
We would recommend setting up the rsync server to allow your DISCO clients (which MUST run as root),
to come in on a non-priveleged, non-root account. You can still use rsync's module definitions with
non-root users by setting up ~/.rsyncd in that user's home directory, and adding
"--rsh 'ssh -l USER_NAME'" to your /disco/client/cmds/rsync parameter on the clients. This will
allow you to specify your rsync locations in your module definitions as USER@HOST::MODULE_NAME instead
of having to specify a filesystem path, will give you all the benefits of an SSH key trust relationship,
and no concern of incoming root access to the server. (Note that this also prevents the often mysterious
and troublesome SSL certificate issues associated with other CI systems.)
2012-08-05 22:11:06 -04:00
2012-08-17 22:35:56 -04:00
Performance Metrics
=====
DISCO stores performance metrics for pretty much everything it does. Use 'disco report' to see them.
The report generated will represent the times and statistics for the most recent disco dance.
2012-08-05 22:11:06 -04:00
The Gory Details ("how does it work?")
=====
DISCO is a work in progress so not all of it is complete, but the general idea is this:
- DISCO client rsyncs its node configuration parameters from the server
- DISCO client performs topological sort of required modules, and for each one:
2012-08-05 22:32:13 -04:00
- fetch all files, templates and scripts
- resolve all templates
2012-08-05 22:11:06 -04:00
- resolve all templates
- execute all scripts
- report all differences
- report overall success or failure (any piece of any module failing indicates failure)
DISCO is able to easily report all differences by executing all scripts and templates inside a
2012-08-05 22:34:08 -04:00
restricted bash chroot, and on top of a read-only unionfs with a scratchpad on the top,
some custom twiddly bits in the middle, and the existing running filesystem at the bottom (read-only).
The scratchpad is not merged if there is a failure during live (non-NOOP) execution, to prevent
from locking the system in a non-functioning state.
If the NOOP flag is set, then all the same operations are performed, but the restricted
environment stops all potentially dangerous commands at the reporting level (presumably), and
the fetched files are not merged out of the scratchpad onto the live filesystem.
2012-08-05 22:11:06 -04:00
See the client disco-fs-* and disco-exec-* scripts for more information on how this is done.
2012-08-17 22:36:31 -04:00
A complete example
=====
Presume we have a server with an incoming user, "disco", who has a home directory like this:
2012-08-17 22:27:58 -04:00
disco@server:~$ cat rsyncd.conf
[parameters]
2012-08-17 22:26:15 -04:00
path = /home/disco/parameters
read only = true
comment = DISCO Parameters
list = yes
use chroot = false
2012-08-17 22:27:58 -04:00
[testmodule-1.0]
2012-08-17 22:26:15 -04:00
path = /home/disco/modules/testmodule-1.0
read only = true
comment = v1.0 of the Test module
list = yes
use chroot = false
2012-08-17 22:27:58 -04:00
[othermodule-3.2]
2012-08-17 22:26:15 -04:00
path = /home/disco/modules/othermodule-3.2
read only = true
comment = v3.2 of othermodule
list = yes
use chroot = false
2012-08-17 22:27:58 -04:00
disco@server:~$ find parameters
parameters
parameters/localhost.localdomain
parameters/localhost.localdomain/parameters
parameters/localhost.localdomain/parameters/something
parameters/localhost.localdomain/modules
parameters/localhost.localdomain/modules/othermodule-3.2
parameters/localhost.localdomain/modules/testmodule-1.0
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
disco@server:~$ cat parameters/localhost.localdomain/parameters/something
LOLTHISKEYMEANSNOTHING
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
disco@server:~$ find modules
modules
modules/othermodule-3.2
modules/othermodule-3.2/requires
modules/othermodule-3.2/parameters
modules/othermodule-3.2/parameters/othermodule-3.2
modules/othermodule-3.2/scripts
modules/othermodule-3.2/templates
modules/othermodule-3.2/templates/etc
modules/othermodule-3.2/templates/etc/othermodule
modules/othermodule-3.2/templates/etc/othermodule/stuff.cfg
modules/othermodule-3.2/files
modules/testmodule-1.0
modules/testmodule-1.0/requires
modules/testmodule-1.0/parameters
modules/testmodule-1.0/parameters/testmodule-1.0
modules/testmodule-1.0/scripts
modules/testmodule-1.0/scripts/00-hello.sh
modules/testmodule-1.0/scripts/10-service_stop.sh
modules/testmodule-1.0/templates
modules/testmodule-1.0/files
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
disco@server:~$ cat modules/othermodule-3.2/templates/etc/othermodule/stuff.cfg
echo HOST=$(hostname)
echo KEY_VALUE=$(cat /var/disco/parameters/$(hostname)/parameters/something)
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
disco@server:~$ cat modules/testmodule-1.0/scripts/00-hello.sh
2012-08-17 22:30:58 -04:00
#!/bin/bash
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
echo "Hello, disco"
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
disco@server:~$ cat modules/testmodule-1.0/scripts/10-service_stop.sh
2012-08-17 22:30:58 -04:00
#!/bin/bash
2012-08-17 22:26:15 -04:00
2012-08-17 22:27:58 -04:00
service postgresql stop
2012-08-17 22:30:58 -04:00
... and that we have, on our client, a disco parameters tree set up like this:
[disco@client disco]$ disco-param dump
disco = {}
disco/client = {}
disco/client/cmds = {}
disco/client/cmds/rsync = rsync -qaWHe "ssh -i /home/disco/.ssh/id_rsa_disco"
disco/server = {}
disco/server/uri = disco@aklabs.net
... Then we can use disco to configure our host.
First we need to mount and initialize disco's testing/noop filesystem as
root on the client.
2012-08-17 22:27:58 -04:00
[root@localhost disco]$ NOOP=true disco-fs-mount
[root@localhost disco]$ NOOP=true disco-fs-init
2012-08-17 22:30:58 -04:00
This will take a minute or two, the init does a lot of work. (But you only
have to run the init once at system start, no matter how many times you
run disco.) Now we can do our noop run:
2012-08-17 22:27:58 -04:00
[disco@localhost disco]$ NOOP=true disco dance
error: othermodule-3.2: rsync: link_stat "/files/*" (in othermodule-3.2) failed: No such file or directory (2)
error: testmodule-1.0: rsync: link_stat "/files/*" (in testmodule-1.0) failed: No such file or directory (2)
info: Processing testmodule-1.0
Hello, disco
warning: Would execute : service postgresql stop
info: Processing othermodule-3.2
info: File: file: /etc/othermodule/stuff.cfg : Created : type=[regular file] device=[fd00] mode=[81a4] selinux=[?] md5=[77b20e4840b1be13a577e152edc6b443] perms=[root:root 644]
0a1,2
> HOST=localhost.localdomain
> KEY_VALUE=LOLTHISKEYMEANSNOTHING
Here we can see the noop at work; it is preventing potentially destructive
commands like 'service' from running, while allowing other harmless commands
to operate in the noop context so that script logic is not affected. We can
also see the highly detailed statistics and diffs returned for file
modifications. But none of the files actually wind up present on the
system, and no running processes were affected:
2012-08-17 22:27:58 -04:00
[root@client ~]$ ps ax | grep -i postgresql
15595 pts/1 S+ 0:00 grep -i postgresql
24457 ? S 0:12 /usr/lib/postgresql/8.4/bin/postgres -D /var/lib/postgresql/8.4/main -c config_file=/etc/postgresql/8.4/main/postgresql.conf
[root@client ~]$ ls -l /etc/othermodule/stuff.cfg
ls: cannot access /etc/othermodule/stuff.cfg: No such file or directory
If we were to turn the NOOP flag off, this would all happen for real:
2012-08-17 22:27:58 -04:00
[root@client disco]$ disco dance
error: othermodule-3.2: rsync: link_stat "/files/*" (in othermodule-3.2) failed: No such file or directory (2)
error: testmodule-1.0: rsync: link_stat "/files/*" (in testmodule-1.0) failed: No such file or directory (2)
info: Processing testmodule-1.0
Hello, disco
info: Processing othermodule-3.2
info: File: file: /etc/othermodule/stuff.cfg : Created : type=[regular file] device=[fd00] mode=[81a4] selinux=[?] md5=[77b20e4840b1be13a577e152edc6b443] perms=[root:root 644]
0a1,2
> HOST=localhost.localdomain
> KEY_VALUE=LOLTHISKEYMEANSNOTHING
... And we will see that the config file has been installed:
2012-08-17 22:27:58 -04:00
[root@client ~]$ cat /etc/othermodule/stuff.cfg
HOST=localhost.localdomain
KEY_VALUE=LOLTHISKEYMEANSNOTHING
... And that postgres has been stopped:
2012-08-17 22:27:58 -04:00
[root@client ~]# ps ax | grep -i postgresql
28394 pts/1 S+ 0:00 grep -i postgresql
Hooray!
Disco will report other types of file modifications, as well. If you were to
open an interactive shell in the disco chroot, and perform some more interesting
operations, representing what a more advanced sort of script might do:
2012-08-17 22:35:56 -04:00
[disco@client disco]$ NOOP=true disco-sh-shell
2012-08-17 22:27:58 -04:00
[root@client /]# rm -f /etc/passwd
[root@client /]# grep -v root /etc/shadow | tee tmpfile
bin:*:15240:0:99999:7:::
daemon:*:15240:0:99999:7:::
adm:*:15240:0:99999:7:::
lp:*:15240:0:99999:7:::
sync:*:15240:0:99999:7:::
shutdown:*:15240:0:99999:7:::
halt:*:15240:0:99999:7:::
mail:*:15240:0:99999:7:::
uucp:*:15240:0:99999:7:::
operator:*:15240:0:99999:7:::
games:*:15240:0:99999:7:::
gopher:*:15240:0:99999:7:::
ftp:*:15240:0:99999:7:::
nobody:*:15240:0:99999:7:::
dbus:!!:15324::::::
usbmuxd:!!:15324::::::
avahi-autoipd:!!:15324::::::
vcsa:!!:15324::::::
rtkit:!!:15324::::::
rpc:!!:15324:0:99999:7:::
pulse:!!:15324::::::
haldaemon:!!:15324::::::
avahi:!!:15324::::::
saslauth:!!:15324::::::
postfix:!!:15324::::::
apache:!!:15324::::::
ntp:!!:15324::::::
rpcuser:!!:15324::::::
nfsnobody:!!:15324::::::
gdm:!!:15324::::::
sshd:!!:15324::::::
tcpdump:!!:15324::::::
disco:$6$Hv67bVi.$d/EolMfURGTMbq1hBr1QL2HdYMYxAXvruq550Qqgu2HCOKWQ1YptMghLKvOAgr3h0NwzXZwHpXQ6fVLdpYe.9.:15533:0:99999:7:::
discostu:!!:15558:0:99999:7:::
[root@client /]# mv tmpfile /etc/shadow
mv: overwrite `/etc/shadow'? y
[root@client /]# echo LOL > /var/lib/p0wnt
bash: /var/lib/p0wnt: restricted: cannot redirect output
[root@client /]# echo LOL | tee /var/lib/p0wnt
LOL
[root@client /]# echo > /bin/myhotbash
bash: /bin/myhotbash: restricted: cannot redirect output
[root@client /]# touch /bin/myhotbash
[root@client /]# exit
... Since that was done inside of the noop shell (where all the scripts and
templates run during noop), we can easily report on these activities:
2012-08-17 22:35:56 -04:00
[disco@client disco]$ NOOP=true disco-fs-diff
2012-08-17 22:27:58 -04:00
info: File: file: /etc/passwd : Deleted
1,35d0
< root:x:0:0:root:/root:/bin/bash
< bin:x:1:1:bin:/bin:/sbin/nologin
< daemon:x:2:2:daemon:/sbin:/sbin/nologin
< adm:x:3:4:adm:/var/adm:/sbin/nologin
< lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
< sync:x:5:0:sync:/sbin:/bin/sync
< shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
< halt:x:7:0:halt:/sbin:/sbin/halt
< mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
< uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
< operator:x:11:0:operator:/root:/sbin/nologin
< games:x:12:100:games:/usr/games:/sbin/nologin
< gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
< ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
< nobody:x:99:99:Nobody:/:/sbin/nologin
< dbus:x:81:81:System message bus:/:/sbin/nologin
< usbmuxd:x:113:113:usbmuxd user:/:/sbin/nologin
< avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
< vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
< rtkit:x:499:496:RealtimeKit:/proc:/sbin/nologin
< rpc:x:32:32:Rpcbind Daemon:/var/cache/rpcbind:/sbin/nologin
< pulse:x:498:495:PulseAudio System Daemon:/var/run/pulse:/sbin/nologin
< haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
< avahi:x:70:70:Avahi mDNS/DNS-SD Stack:/var/run/avahi-daemon:/sbin/nologin
< saslauth:x:497:76:"Saslauthd user":/var/empty/saslauth:/sbin/nologin
< postfix:x:89:89::/var/spool/postfix:/sbin/nologin
< apache:x:48:48:Apache:/var/www:/sbin/nologin
< ntp:x:38:38::/etc/ntp:/sbin/nologin
< rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
< nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
< gdm:x:42:42::/var/lib/gdm:/sbin/nologin
< sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
< tcpdump:x:72:72::/:/sbin/nologin
< disco:x:500:10::/home/disco:/bin/bash
< discostu:x:501:501::/home/discostu:/bin/bash
info: File: file: /bin/myhotbash : Created : type=[regular empty file] device=[fd00] mode=[81a4] selinux=[?] md5=[d41d8cd98f00b204e9800998ecf8427e] perms=[root:root 644]
info: File: file: /etc/shadow : Modified : md5=[8b02f6d00dbcd622f869216bb1dbbbf4 => 336d0b913c8f8cd029964afd00357952] perms=[root:root 0 => root:root 644] mode=[8000 => 81a4]
1d0
< root:$6$57kBYzwRrygFb5op$vghIbLjxmkzTznSbN4kA5fdxFsd1ye7WWe/HFtwMJSTBlDuBcOZISgLKNg/xlA4uAFIBi82yAnW/JajgwhCXY.:15517:0:99999:7:::
info: File: file: /root/.bash_history : Modified : md5=[ead812e487da32cb99cebd09ad7f773b => cb0138b7f3c4f48639cafe9f7147413f] selinux=[unconfined_u:object_r:admin_home_t:s0 => ?]
228a229,237
> exit
> rm -f /etc/passwd
> grep -v root /etc/shadow | tee tmpfile
> mv tmpfile /etc/shadow
> echo LOL > /var/lib/p0wnt
> echo LOL | tee /var/lib/p0wnt
> echo > /bin/myhotbash
> touch /bin/myhotbash
> exit
info: File: file: /var/lib/p0wnt : Created : type=[regular file] device=[fd00] mode=[81a4] selinux=[?] md5=[5732edd7e4e1240b868e15bc95d36339] perms=[root:root 644]
0a1
> LOL
And here we see some more of Disco's rather extensive noop reporting capabilities.
But let's say that this run took longer than we thought it should. What was taking
so much time? Disco will tell us.
2012-08-17 22:35:56 -04:00
[root@disco ~]# disco report
2012-08-17 22:27:58 -04:00
report: _internal: diff
report: time_real 0.82 : time_user 0.14 : time_sys 0.66
report: mem_avg 0 : mem_max 5184 : mem_faults_major 0 : mem_faults_minor 18218
report: io_fsin 0 : io_fsout 8 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
report: _internal: fetch_params
2012-08-19 05:31:11 -04:00
report: time_real 1.26 : time_user 0.02 : time_sys 0.08
report: mem_avg 0 : mem_max 11136 : mem_faults_major 0 : mem_faults_minor 1728
2012-08-17 22:27:58 -04:00
report: io_fsin 0 : io_fsout 0 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
2012-08-19 05:31:11 -04:00
report: othermodule-3.2: diff
report: time_real 0.80 : time_user 0.13 : time_sys 0.65
report: mem_avg 0 : mem_max 4816 : mem_faults_major 0 : mem_faults_minor 16448
report: io_fsin 0 : io_fsout 8 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
2012-08-17 22:27:58 -04:00
report: othermodule-3.2: fetch
2012-08-19 05:31:11 -04:00
report: time_real 2.28 : time_user 0.05 : time_sys 0.14
report: mem_avg 0 : mem_max 11152 : mem_faults_major 0 : mem_faults_minor 2843
2012-08-17 22:27:58 -04:00
report: io_fsin 0 : io_fsout 24 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
report: othermodule-3.2: template
report: etc/othermodule/stuff.cfg :
2012-08-19 05:31:11 -04:00
report: time_real 0.56 : time_user 0.04 : time_sys 0.37
report: mem_avg 0 : mem_max 4592 : mem_faults_major 122 : mem_faults_minor 4885
2012-08-17 22:27:58 -04:00
report: io_fsin 25536 : io_fsout 16 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
2012-08-19 05:31:11 -04:00
report: testmodule-1.0: diff
report: time_real 2.56 : time_user 0.42 : time_sys 2.10
report: mem_avg 0 : mem_max 5184 : mem_faults_major 0 : mem_faults_minor 57661
report: io_fsin 0 : io_fsout 32 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
2012-08-17 22:27:58 -04:00
report: testmodule-1.0: exec
report: 00-hello.sh :
2012-08-19 05:31:11 -04:00
report: time_real 0.27 : time_user 0.03 : time_sys 0.18
report: mem_avg 0 : mem_max 4672 : mem_faults_major 32 : mem_faults_minor 3783
report: io_fsin 6640 : io_fsout 8 : io_sockin 0 : io_sockout 0 : io_signals 0
2012-08-17 22:27:58 -04:00
report: exit: 0
report: 10-service_stop.sh :
2012-08-19 05:31:11 -04:00
report: time_real 0.58 : time_user 0.03 : time_sys 0.41
report: mem_avg 0 : mem_max 4960 : mem_faults_major 122 : mem_faults_minor 5462
report: io_fsin 25656 : io_fsout 8 : io_sockin 0 : io_sockout 0 : io_signals 0
2012-08-17 22:27:58 -04:00
report: exit: 1
report: testmodule-1.0: fetch
2012-08-19 05:31:11 -04:00
report: time_real 2.72 : time_user 0.06 : time_sys 0.15
report: mem_avg 0 : mem_max 11152 : mem_faults_major 0 : mem_faults_minor 2996
2012-08-17 22:27:58 -04:00
report: io_fsin 0 : io_fsout 24 : io_sockin 0 : io_sockout 0 : io_signals 0
report: exit: 0
Happy dancing!