Merge lp:~jtv/maas/single-cluster into lp:~maas-committers/maas/trunk

Proposed by Jeroen T. Vermeulen
Status: Merged
Merged at revision: 7
Proposed branch: lp:~jtv/maas/single-cluster
Merge into: lp:~maas-committers/maas/trunk
Diff against target: 295 lines (+82/-39)
6 files modified
.bzrignore (+1/-0)
Makefile (+11/-8)
README.txt (+14/-13)
bin/maasdb (+45/-10)
src/maas/development.py (+1/-1)
src/maas/settings.py (+10/-7)
To merge this branch: bzr merge lp:~jtv/maas/single-cluster
Reviewer Review Type Date Requested Status
Gavin Panella (community) Approve
Review via email: mp+88739@code.launchpad.net

Commit message

Single development db cluster per branch.

Description of the change

Allocate just a single local database cluster per branch, and make sure the "make" targets that need it will start it up. Also, rename maasdb.sh to maasdb and add a simple command set so it's easier to use.

Finally, update settings.py with the applicable changes we've made in development.py.

To post a comment you must log in.
Revision history for this message
Gavin Panella (allenap) wrote :

[1]

-build: bin/buildout
+build: bin/buildout dev-db

I know it's early days, but we probably don't want to create the dev
database for just a build.

[2]

-run:
+run: build
  bin/django runserver 8000

If you agree with [1] then this needs to depend on build and dev-db.

[3]

-harness:
- . bin/maasdb.sh ; maasdb_init_db db/development disposable
+harness: dev-db
  bin/django shell

-syncdb:
+syncdb: dev-db
  bin/django syncdb

However, these don't depend on build, so perhaps run doesn't need to
either.

[4]

+main() {
+ COMMAND="$1"

COMMAND will end up in the calling environment. The local command
sorts this out:

main() {
    local COMMAND="$1"

Please also let's not pretend we're writing for a plain /bin/sh; let's
just use bash and not go quite as insane. Or, read [6] and use Python,
or just about anything *but* shell.

[5]

+if test -n "$*"
+then
+ main $*
+fi

This won't work if sourced within a script that itself has args, or if
"set -- $something" has been used in the shell before sourcing this
script. Because main() defaults to doing nothing if the argument does
not match I think it's safe to just call main() unconditionally.

[6]

+ case $COMMAND in
+ start) maasdb_init_db $* ;;
+ stop) maasdb_stop_cluster $* ;;
+ query) maasdb_query $* ;;
+ shell) maasdb_shell $* ;;
+ delete-cluster) maasdb_delete_cluster $* ;;
+ esac
...
+ main $*

Avoid $* because it rarely does the right thing (in bash at
least). Also, more quotes needed. The code above behaves badly if
there are spaces in the arguments passed in. I think the following
will work without surprises:

main() {
    COMMAND="$1"
    shift
    case "$COMMAND" in
        start) maasdb_init_db "$@" ;;
        stop) maasdb_stop_cluster "$@" ;;
        query) maasdb_query "$@" ;;
        shell) maasdb_shell "$@" ;;
        delete-cluster) maasdb_delete_cluster "$@" ;;
    esac
}

if [ $# -gt 1 ]
then
    main "$@"
fi

Similar modifications ought to be made throughout the script.

To be honest, having to remember crap like this makes me avoid shell
script these days for anything other than the very most trivial
things.

review: Needs Fixing
Revision history for this message
Jeroen T. Vermeulen (jtv) wrote :

Thanks for the review. I learned several new things.

> [1]
>
> -build: bin/buildout
> +build: bin/buildout dev-db
>
> I know it's early days, but we probably don't want to create the dev
> database for just a build.

Done.

> [2]
>
> -run:
> +run: build
> bin/django runserver 8000
>
> If you agree with [1] then this needs to depend on build and dev-db.

Done.

> [3]
>
> -harness:
> - . bin/maasdb.sh ; maasdb_init_db db/development disposable
> +harness: dev-db
> bin/django shell
>
> -syncdb:
> +syncdb: dev-db
> bin/django syncdb
>
> However, these don't depend on build, so perhaps run doesn't need to
> either.

It turned out they should have depended on build. Fixed.

> [4]
>
> +main() {
> + COMMAND="$1"
>
> COMMAND will end up in the calling environment. The local command
> sorts this out:

Done, thanks. Wasn't aware of "local."

> [5]
>
> +if test -n "$*"
> +then
> + main $*
> +fi
>
> This won't work if sourced within a script that itself has args, or if
> "set -- $something" has been used in the shell before sourcing this
> script. Because main() defaults to doing nothing if the argument does
> not match I think it's safe to just call main() unconditionally.

Note that this branch eliminates sourcing of the script entirely. I updated comments to remove any suggestion of sourcing it.

> [6]
>
> + case $COMMAND in
> + start) maasdb_init_db $* ;;
> + stop) maasdb_stop_cluster $* ;;
> + query) maasdb_query $* ;;
> + shell) maasdb_shell $* ;;
> + delete-cluster) maasdb_delete_cluster $* ;;
> + esac
> ...
> + main $*
>
> Avoid $* because it rarely does the right thing (in bash at
> least). Also, more quotes needed. The code above behaves badly if
> there are spaces in the arguments passed in. I think the following
> will work without surprises:
>
> main() {
> COMMAND="$1"
> shift
> case "$COMMAND" in
> start) maasdb_init_db "$@" ;;
> stop) maasdb_stop_cluster "$@" ;;
> query) maasdb_query "$@" ;;
> shell) maasdb_shell "$@" ;;
> delete-cluster) maasdb_delete_cluster "$@" ;;
> esac
> }

I wasn't aware of $@ either; reading up on it gave me a much clearer understanding of shell quoting. But since there is no longer any pretense that the functions in the script are for external use, I now shift both the command and the data dir (and fail if they are not given).

> if [ $# -gt 1 ]
> then
> main "$@"
> fi
>
> Similar modifications ought to be made throughout the script.

I don't see any other place where I'd need to make these particular changes.

> To be honest, having to remember crap like this makes me avoid shell
> script these days for anything other than the very most trivial
> things.

You've sold me. This script should not grow; it's just a minimal toolbox.

Jeroen

Revision history for this message
Gavin Panella (allenap) wrote :

Looks good, I think this will work well.

[7]

+main $*

I think this still needs to change to

main "$@"

to avoid whitespace issues.

review: Approve
Revision history for this message
Gavin Panella (allenap) wrote :

> I don't see any other place where I'd need to make these particular changes.

Ah, um, yeah :)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file '.bzrignore'
2--- .bzrignore 2012-01-16 16:30:23 +0000
3+++ .bzrignore 2012-01-17 10:01:24 +0000
4@@ -2,6 +2,7 @@
5 bin/django
6 bin/test
7 build
8+db
9 develop-eggs
10 download-cache
11 eggs
12
13=== modified file 'Makefile'
14--- Makefile 2012-01-16 15:53:24 +0000
15+++ Makefile 2012-01-17 10:01:24 +0000
16@@ -8,22 +8,26 @@
17 bin/buildout
18 @touch bin/buildout
19
20-test:
21+dev-db:
22+ bin/maasdb start ./db/ disposable
23+
24+test: dev-db
25 bin/test
26
27 lint:
28 pyflakes $(PYTHON_SRC)
29 pylint --rcfile=etc/pylintrc $(PYTHON_SRC)
30
31-check: clean bin/buildout
32+check: clean bin/buildout dev-db
33 bin/test
34
35 clean:
36 find . -type f -name '*.py[co]' -exec rm -f {} \;
37- #rm -f bin/buildout
38+ rm -f bin/buildout
39 #bzr clean-tree --unknown --force
40
41-realclean: clean
42+distclean: clean
43+ bin/maasdb delete-cluster ./db/
44 rm -rf download-cache
45 rm -rf eggs
46 rm -rf develop-eggs
47@@ -31,12 +35,11 @@
48 tags:
49 bin/tags
50
51-run:
52+run: build dev-db
53 bin/django runserver 8000
54
55-harness:
56- . bin/maasdb.sh ; maasdb_init_db db/development disposable
57+harness: build dev-db
58 bin/django shell
59
60-syncdb:
61+syncdb: build dev-db
62 bin/django syncdb
63
64=== modified file 'README.txt'
65--- README.txt 2012-01-16 08:33:18 +0000
66+++ README.txt 2012-01-17 10:01:24 +0000
67@@ -3,21 +3,17 @@
68 For more information about MaaS:
69 https://launchpad.net/maas
70
71+
72 = Development MaaS server setup =
73
74-You need a database for the maas server.
75-
76-You can choose to use the database of your choice (note that you will
77-need to update the default values in src/maas/development.py if you choose
78-to do so).
79-
80-If you want to use the default for a local development server (postgresql
81-database engine, user: 'maas' with 'maas' as password, database name: 'maas'):
82-
83- $ echo "CREATE USER maas WITH CREATEDB PASSWORD 'maas';" | psql -U postgres
84- $ createdb -E utf8 -O maas maas
85-
86-Setup the project (fetch all the required dependencies):
87+Access to the database is configured in src/maas/development.py.
88+
89+The Makefile sets up a development database cluster inside your branch. It
90+lives in the "db" directory, which gets created on demand. You'll want to
91+shut it down before deleting a branch; see below.
92+
93+First, set up the project. This fetches all the required dependencies, and
94+creates a local database cluster and development database:
95
96 $ make
97
98@@ -30,3 +26,8 @@
99 $ make run
100
101 Point your browser to http://localhost:8000/
102+
103+To shut down the database cluster and clean up all other generated files in
104+your branch:
105+
106+ $ make distclean
107
108=== renamed file 'bin/maasdb.sh' => 'bin/maasdb' (properties changed: -x to +x)
109--- bin/maasdb.sh 2012-01-16 14:49:10 +0000
110+++ bin/maasdb 2012-01-17 10:01:24 +0000
111@@ -1,15 +1,15 @@
112-# MaaS database control functions
113-#
114-# The control functions take as their first argument a database cluster's data
115+#! /bin/bash -e
116+#
117+# MaaS database control script
118+#
119+# Most functions take as their first argument a database cluster's data
120 # directory. This is where the database's socket, pidfile, log, and data will
121-# reside. The data directory must start with a slash.
122+# reside.
123 #
124 # Some design choices for this module:
125 #
126 # * Everything is PostgreSQL on Ubuntu.
127-# * POSIX shell. Test your changes in dash, not just in bash.
128-# * Each branch gets its own cluster(s). Kill & delete when done.
129-# * One database per cluster. May change this later if it's a problem.
130+# * Each branch gets its own cluster. Kill & delete when done.
131 # * Databases run under the system user that creates them. No root required.
132 # * No global configuration apart from a basic PostgreSQL install.
133 # * Connections use Unix sockets. No TCP port hogging.
134@@ -18,10 +18,12 @@
135 PGCTL="/usr/lib/postgresql/${POSTGRES_VERSION}/bin/pg_ctl"
136
137
138-# Figure out the full data directory path for a given cluster, even if it's a
139-# relative path.
140+# Figure out the full absolute data directory path for a given cluster, even
141+# if a relative path is given.
142 maasdb_locate() {
143+ local DATADIR
144 DATADIR="$1"
145+
146 if test -z "$1"
147 then
148 echo "Specify a data directory for the MaaS database cluster." >&2
149@@ -36,7 +38,9 @@
150
151 # Create a database cluster.
152 maasdb_create_cluster() {
153+ local DATADIR
154 DATADIR="`maasdb_locate "$1"`"
155+
156 if ! test -d "$DATADIR/base"
157 then
158 mkdir -p -- "$DATADIR"
159@@ -47,6 +51,7 @@
160
161 # Start a database cluster.
162 maasdb_start_cluster() {
163+ local DATADIR DISPOSABLE EXTRA_POSTGRES_OPTS
164 DATADIR="`maasdb_locate "$1"`"
165 # Pass "disposable" as the second argument if the data in this database
166 # is not important at all and you're willing to cut corners for speed.
167@@ -80,7 +85,9 @@
168
169 # Stop a database cluster.
170 maasdb_stop_cluster() {
171+ local DATADIR
172 DATADIR="`maasdb_locate "$1"`"
173+
174 if test -f "$DATADIR/postmaster.pid"
175 then
176 $PGCTL stop -D "$DATADIR"
177@@ -90,12 +97,15 @@
178
179 # Initialize a MaaS database.
180 maasdb_init_db() {
181+ local DATADIR DISPOSABLE MARKER
182 DATADIR="`maasdb_locate "$1"`"
183 # Pass "disposable" as the second argument if the data in this database
184 # is not important at all and you're willing to cut corners for speed.
185 DISPOSABLE="$2"
186+
187+ maasdb_start_cluster "$DATADIR" "$DISPOSABLE"
188+
189 MARKER="$DATADIR/maas-created"
190- maasdb_start_cluster "$DATADIR" "$DISPOSABLE"
191 if ! test -f "$MARKER"
192 then
193 createdb -h "$DATADIR" maas && touch "$MARKER"
194@@ -105,7 +115,9 @@
195
196 # Open a psql shell on a MaaS database.
197 maasdb_shell() {
198+ local DATADIR
199 DATADIR="`maasdb_locate "$1"`"
200+
201 maasdb_init_db "$DATADIR"
202 psql -h "$DATADIR" maas
203 }
204@@ -113,8 +125,10 @@
205
206 # Execute a query on a MaaS database.
207 maasdb_query() {
208+ local DATADIR QUERY
209 DATADIR="`maasdb_locate "$1"`"
210 QUERY="$2"
211+
212 maasdb_init_db "$DATADIR"
213 psql -h "$DATADIR" maas -c "$QUERY"
214 }
215@@ -122,7 +136,9 @@
216
217 # Delete an entire MaaS database and cluster. Use only with extreme care!
218 maasdb_delete_cluster() {
219+ local DATADIR
220 DATADIR="`maasdb_locate "$1"`"
221+
222 # Before deleting anything, does this at least look like a MaaS database
223 # cluster?
224 if test -d "$DATADIR/base"
225@@ -131,3 +147,22 @@
226 rm -rf -- "$DATADIR"
227 fi
228 }
229+
230+
231+main() {
232+ local COMMAND DATADIR
233+ COMMAND="$1"
234+ DATADIR="$2"
235+ shift 2
236+
237+ case "$COMMAND" in
238+ start) maasdb_init_db "$DATADIR" "$@" ;;
239+ stop) maasdb_stop_cluster "$DATADIR" "$@" ;;
240+ query) maasdb_query "$DATADIR" "$@" ;;
241+ shell) maasdb_shell "$DATADIR" "$@" ;;
242+ delete-cluster) maasdb_delete_cluster "$DATADIR" "$@" ;;
243+ esac
244+}
245+
246+
247+main $*
248
249=== modified file 'src/maas/development.py'
250--- src/maas/development.py 2012-01-16 16:24:00 +0000
251+++ src/maas/development.py 2012-01-17 10:01:24 +0000
252@@ -24,7 +24,7 @@
253 'NAME': 'maas',
254 # For PostgreSQL, a "hostname" starting with a slash indicates a
255 # Unix socket directory.
256- 'HOST': '%s/db/development' % os.getcwd(),
257+ 'HOST': '%s/db' % os.getcwd(),
258 }
259 }
260
261
262=== modified file 'src/maas/settings.py'
263--- src/maas/settings.py 2012-01-16 16:15:44 +0000
264+++ src/maas/settings.py 2012-01-17 10:01:24 +0000
265@@ -17,12 +17,15 @@
266
267 DATABASES = {
268 'default': {
269- 'ENGINE': 'django.db.backends.', # Add 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' or 'oracle'.
270- 'NAME': '', # Or path to database file if using sqlite3.
271- 'USER': '', # Not used with sqlite3.
272- 'PASSWORD': '', # Not used with sqlite3.
273- 'HOST': '', # Set to empty string for localhost. Not used with sqlite3.
274- 'PORT': '', # Set to empty string for default. Not used with sqlite3.
275+ # 'postgresql_psycopg2', 'postgresql', 'mysql', 'sqlite3' etc.
276+ 'ENGINE': 'django.db.backends.postgresql_psycopg2',
277+ 'NAME': 'maas',
278+ 'USER': '',
279+ 'PASSWORD': '',
280+ # For PostgreSQL, a "hostname" starting with a slash indicates a
281+ # Unix socket directory.
282+ 'HOST': '',
283+ 'PORT': '',
284 }
285 }
286
287@@ -33,7 +36,7 @@
288 # timezone as the operating system.
289 # If running in a Windows environment this must be set to the same as your
290 # system time zone.
291-TIME_ZONE = 'America/Chicago'
292+TIME_ZONE = None
293
294 # Language code for this installation. All choices can be found here:
295 # http://www.i18nguy.com/unicode/language-identifiers.html