j@279
|
1 (cl:in-package #:amuse-database-admin)
|
j@279
|
2
|
j@279
|
3 (defparameter *amuse-database* nil)
|
j@279
|
4
|
j@279
|
5 (defun connect-to-database (&key (database-name "amuse") username
|
j@279
|
6 use-tunnel (make-default t))
|
j@279
|
7 "Well, slightly more secure I guess. Requires that an option file
|
j@279
|
8 exists containing connection-spec s-expressions. If no such file
|
j@279
|
9 exists a skeleton file can be created by calling
|
j@279
|
10 make-db-option-file (the password still needs to be added
|
j@279
|
11 manually). The path is ~/.amuse.lisp.
|
j@279
|
12
|
j@279
|
13 A better approach might be to use something like:
|
j@279
|
14 http://www.cliki.net/trivial-configuration-parser. Or for slime to
|
j@279
|
15 prompt the user for the password something
|
j@279
|
16 like (swank::eval-in-emacs `(read-passwd \"Password: \")). However,
|
j@279
|
17 this presents other security issues.
|
j@279
|
18
|
j@279
|
19 If use-tunnel is t, then regardless of the host specified in the
|
j@279
|
20 connection-spec, it will be set to localhost. It is assumed that the
|
j@279
|
21 tunnel is already set up.
|
j@279
|
22
|
j@279
|
23 When make-default is t, the newly created connection is assigned to
|
j@279
|
24 *amuse-database*. If make-default is nil, then the connection is
|
j@279
|
25 returned and is expected to be handled by the caller. This is useful
|
j@279
|
26 for connecting to different databases within individual
|
j@279
|
27 implementations (mainly for testing purposes)."
|
j@279
|
28 (if (and make-default
|
j@279
|
29 *amuse-database*
|
j@279
|
30 (clsql-mysql::is-database-open *amuse-database*))
|
j@279
|
31 (error "A default AMuSE database connection already exists:
|
j@279
|
32 ~S" (clsql:database-name *amuse-database*))
|
j@279
|
33 (let ((connection-spec (%get-connection-spec database-name
|
j@279
|
34 username)))
|
j@279
|
35 (when use-tunnel
|
j@279
|
36 (setf (car connection-spec) "127.0.0.1"))
|
j@279
|
37 (let ((connection (%get-database-connection connection-spec)))
|
j@279
|
38 (when make-default
|
j@279
|
39 (setf *amuse-database* connection))
|
j@279
|
40 connection))))
|
j@279
|
41
|
j@279
|
42 (defun disconnect-from-database (&optional (database-connection
|
j@279
|
43 *amuse-database*))
|
j@279
|
44 (clsql:disconnect :database database-connection))
|
j@279
|
45
|
j@279
|
46 (defun make-db-option-file (&key database-name host username (port "3306"))
|
j@279
|
47 (with-open-file (stream (%make-db-option-file-pathname) :direction :output)
|
j@279
|
48 (sb-ext:run-program "chmod"
|
j@279
|
49 (list "600" (namestring
|
j@279
|
50 (%make-db-option-file-pathname)))
|
j@279
|
51 :search t)
|
j@279
|
52 (princ "
|
j@279
|
53 ;;; Option file containing connection-spec s-expressions for connecting
|
j@279
|
54 ;;; to a database from within AMuSE. You can have multiple specifications,
|
j@279
|
55 ;;; but they must be uniquely identifiable by database name or a combination
|
j@279
|
56 ;;; of database and username.
|
j@279
|
57
|
j@279
|
58 ;;; You need to fill in the missing <details>." stream)
|
j@279
|
59 (format stream "~2%(~S ~S ~S \"<pwd>\" ~S)"
|
j@279
|
60 (if host host "<host>")
|
j@279
|
61 (if database-name database-name "<db-name>")
|
j@279
|
62 (if username username "<username>")
|
j@279
|
63 port))
|
j@279
|
64 (warn "You now need to manually edit ~A."
|
j@279
|
65 (namestring (%make-db-option-file-pathname))))
|
j@279
|
66
|
j@279
|
67 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
j@279
|
68 ;;; Helper functions
|
j@279
|
69
|
j@279
|
70 (defun %get-database-connection (connection-spec)
|
j@279
|
71 (clsql:connect connection-spec
|
j@279
|
72 :if-exists :old
|
j@279
|
73 :database-type :mysql))
|
j@279
|
74
|
j@279
|
75 (defun %get-connection-spec (db-name username)
|
j@279
|
76 (let ((option-file (probe-file (%make-db-option-file-pathname))))
|
j@279
|
77 (if option-file
|
j@279
|
78 (with-open-file (stream option-file)
|
j@279
|
79 (loop for connection-spec = (read stream nil)
|
j@279
|
80 while connection-spec
|
j@279
|
81 do (destructuring-bind (host db usr pwd prt)
|
j@279
|
82 connection-spec
|
j@279
|
83 (declare (ignore host pwd prt))
|
j@279
|
84 (when (equal db-name db)
|
j@279
|
85 (when (or (null username)
|
j@279
|
86 (equal username usr))
|
j@279
|
87 (return connection-spec))))
|
j@279
|
88 finally (error "No connection-spec exists matching
|
j@279
|
89 database: ~A and username: ~A" db-name username)))
|
j@279
|
90 ;; If file doesn't exist, create it.
|
j@279
|
91 (error "~A option file does not exist.
|
j@279
|
92 You need to run: amuse-database-admin:make-db-option-file."
|
j@279
|
93 (namestring (%make-db-option-file-pathname))))))
|
j@279
|
94
|
j@279
|
95 (defun %make-db-option-file-pathname ()
|
j@279
|
96 (merge-pathnames (user-homedir-pathname) ".amuse.lisp"))
|