Statistics
| Branch: | Tag: | Revision:

root / README.develop @ fc2afa67

History | View | Annotate | Download (10.9 kB)

1
DEVELOP.txt - Information on how to setup a development environment. 
2

    
3
Dependencies
4
------------
5

    
6
Synnefo is written in Python 2.6 and depends on the following Python modules
7
[package versions confirmed to be compatible are in braces]
8

    
9
- django 1.2 [Django==1.2.4]
10
- simplejson [simplejson==2.1.3]
11
- pycurl [pycurl==7.19.0]
12
- python-dateutil  [python-dateutil==1.4.1]
13
  WARNING: version python-dateutil==2.0 downloaded by pip known *not* to work
14
           with Python 2.6
15
- south [south==0.7.1]
16
  WARNING: not working with Debian squeeze's default south-0.7-1 package.
17
- amqplib [amqplib==0.6.1]
18

    
19
also, depending on the database engine of choice, on one of the following:
20
- MySQL-python [MySQL-python==1.2.3]
21
- psycopg2 [psycopg2==2.4]
22

    
23
if the invitations application is deployed, the following
24
dependencies should be installed
25

    
26
- pycrypto==2.1.0
27

    
28
if you want to test the ganeti (FIXME)
29

    
30
to run the user interface tests, selenium must be installed
31
- selenium [?]
32

    
33
Preparing the development environment
34
-------------------------------------
35

    
36
1. Prepare the system: The easiest method is to setup a working environment
37
through virtualenv. Alternatively, you can use your system's package manager
38
to install the dependencies (e.g. Macports has them all).
39

    
40
* On Snow Leopard and linux (64-bit), you have to set the following environment
41
  variable for pip to compile the dependencies correctly.
42

    
43
	$ export ARCHFLAGS="-arch x86_64"
44

    
45
* On Ubuntu, a few more packages must be installed before installing the
46
  prerequisite Python libraries
47

    
48
	$ sudo aptitude install libcurl3-gnutls libcurl3-gnutls-dev uuid-dev 
49

    
50
2. Checkout the code and install the Python prerequisites. This assumes
51
that python is already installed on the host.
52

    
53
    $ sudo easy_install virtualenv
54
    $ git clone https://user@code.grnet.gr/git/synnefo synnefo
55
    $ virtualenv --python=python2.6 synnefo --no-site-packages
56
    ...
57
    $ cd synnefo
58
    $ ./bin/pip install <list_of_prerequisites>
59

    
60
3. At this point you should have all required dependencies installed. Now you
61
have to select a database engine. The choices are: postgres, mysql and sqlite.
62

    
63
- SQLite
64
The python sqlite driver is available by default with Python so no additional 
65
configuration is required. Also, most self-respecting systems have the sqlite 
66
library installed by default.   
67

    
68
- MySQL
69
MySQL must be installed first
70

    
71
* Ubuntu - Debian
72
	$ sudo apt-get install libmysqlclient-dev
73

    
74
* MacPorts
75
	$sudo port install mysql5
76

    
77
Install the MySQL python library
78

    
79
	$ bin/pip install MySQL-python
80

    
81
Note: On MacOSX with Mysql install from MacPorts the above command will fail
82
complaining that it cannot find the mysql_config command. Do the following and
83
restart the installation
84

    
85
	$ echo "mysql_config = /opt/local/bin/mysql_config5" >> ./build/MySQL-python/site.cfg
86

    
87
Configure a MySQL db/account for synnefo
88

    
89
	$ mysql -u root -p
90

    
91
	mysql> create database synnefo;
92
	mysql> show databases;
93
	mysql> GRANT ALL on synnefo.* TO username IDENTIFIED BY 'password';
94
 
95
- Postgres
96

    
97
# Ubuntu - Debian
98
	$ sudo apt-get install postgresql-8.4 libpq-dev
99

    
100
# MacPorts
101
	$ sudo port install postgresql84
102

    
103
Install the postgres Python library
104

    
105
	$ bin/pip install psycopg2
106

    
107
Configure a postgres db/account for synnefo
108
	Become the postgres user, connect to PostgreSQL:
109
	$ sudo su - postgres 
110
	$ psql
111
	
112
	Run the following commands:
113
	DROP DATABASE synnefo;
114
	DROP USER username;
115
	CREATE USER username WITH PASSWORD 'password';
116
	CREATE DATABASE synnefo;
117
	GRANT ALL PRIVILEGES ON DATABASE synnefo TO username;
118
	ALTER DATABASE synnefo OWNER TO username;
119
	ALTER USER username CREATEDB;
120

    
121
The last line enables the newly created user to create own databases. This is
122
needed for Django to create and drop the test_synnefo database for unit
123
testing.
124
	
125
4. At this point you should have a working DB. Now configure Django to access it: 
126
Copy the default configuration file 
127

    
128
    $ cp settings.py.dist settings.py
129
    
130
and then copy/edit according to the database used:  
131
    
132
- SQLite
133

    
134
	PROJECT_PATH = os.path.dirname(os.path.abspath(__file__)) + '/'
135

    
136
	DATABASES = {
137
	    'default': {
138
		'ENGINE': 'django.db.backends.sqlite3',
139
		'NAME': PROJECT_PATH + 'synnefo.db' #WARN: This must be an absolute path
140
	    }
141
	}
142

    
143
- MySQL
144
	DATABASES = {
145
	    'default': {
146
		'ENGINE': 'django.db.backends.mysql', 
147
		'NAME': 'synnefo',
148
		'USER': 'USERNAME',
149
		'PASSWORD': 'PASSWORD',
150
		'HOST': 'HOST',
151
		'PORT': 'PORT',
152
		'OPTIONS': {
153
		    'init_command': 'SET storage_engine=INNODB',
154
		}
155
	    }
156
	}
157

    
158
- Postgres    
159

    
160
    DATABASES = {
161
	    'default': {
162
		'ENGINE': 'django.db.backends.postgresql_psycopg2',
163
		'NAME': 'DATABASE',
164
		'USER': 'USERNAME',
165
		'PASSWORD': 'PASSWORD',
166
		'HOST': 'HOST',
167
		'PORT': 'PORT',
168
	    }
169
	}
170

    
171
5. Try it out. The following command will attempt to connect to the DB and 
172
print out DDL statements. It should not fail.
173

    
174
	$ ./bin/python manage.py sql db
175
	
176
6. Create the DB and load initial data:
177
    
178
	$ ./bin/python manage.py syncdb
179
	$ ./bin/python manage.py migrate db
180
	$ ./bin/python manage.py loaddata db/fixtures/flavors.json
181
	$ ./bin/python manage.py loaddata db/fixtures/images.json
182

    
183
The following fixtures can be loaded optionally depending on
184
testing requirements:
185

    
186
	$ ./bin/python manage.py loaddata db/fixtures/vms.json
187
	$ ./bin/python manage.py loaddata db/fixtures/disks.json
188

    
189
7. Set the BACKEND_PREFIX_ID variable to some unique prefix, e.g. your commit
190
   username in settings.py. Several functional conventions within the system
191
   require this variable to include a dash at its end (e.g. snf-)
192

    
193
8. Fix the AMQP-specific settings based on the selected BACKEND_PREFIX_ID.
194
   The fix_amqp_settings() function is called once at the end of
195
   settings.py.dist, you must call it again if you change BACKEND_PREFIX_ID
196
   at some later point.
197
   Also make sure that if /var/log/synnefo/dispatcher.log exists, it has proper
198
   permissions. If not, /var/log/synnefo/ should be writable by the dispatcher.
199

    
200
9. Start the system
201
    $ ./bin/python logic/dispatcher.py  # DB synch daemon
202
    $ ./bin/python manage.py runserver  # Django
203

    
204
10. (Hopefully) Done
205

    
206

    
207
South Database Migrations
208
------------------------
209

    
210
* Initial Migration
211

    
212
First, remember to add the south app to settings.py (it is already included in
213
the settings.py.dist).
214

    
215
To initialise south migrations in your database the following commands must be
216
executed:
217

    
218
    $ ./bin/python manage.py syncdb       # Create / update the database with the south tables
219
    $ ./bin/python manage.py migrate db   # Perform migration in the database
220

    
221
Note that syncdb will create the latest models that exist in the db app, so
222
some migrations may fail.  If you are sure a migration has already taken place
223
you must use the "--fake" option, to apply it.
224

    
225
For example:
226

    
227
    $ ./bin/python manage.py migrate db 0001 --fake
228

    
229
To be sure that all migrations are applied type:
230

    
231
    $ ./bin/python manage.py migrate db --list
232

    
233
All starred migrations are applied.
234

    
235
Remember, the migration is performed mainly for the data, not for the database
236
schema. If you do not want to migrate the data, a syncdb and fake migrations
237
for all the migration versions will suffice.
238

    
239
* Schema migrations:
240

    
241
Do not use the syncdb management command. It can only be used
242
the first time and/or if you drop the database and must recreate it from
243
scratch.
244
See "Initial Migration" section.
245

    
246
Every time you make changes to the database and data migration is not required
247
(WARNING: always perform this with extreme care):
248

    
249
    $ ./bin/python manage.py schemamigration db --auto
250

    
251
The above will create the migration script. Now this must be applied to the
252
live database.
253

    
254
    $ ./bin/python migrate db
255

    
256
Consider this example (adding a field to the SynnefoUser model):
257

    
258
    bkarak@nefarian:~/devel/synnefo$ ./bin/python manage.py schemamigration db --auto
259
     + Added field new_south_test_field on db.SynnefoUser
260
     Created 0002_auto__add_field_synnefouser_new_south_test_field.py.
261

    
262
  You can now apply this migration with: ./manage.py migrate db
263

    
264
    $ ./manage.py migrate db
265
     Running migrations for db:
266
     - Migrating forwards to 0002_auto__add_field_synnefouser_new_south_test_field.
267
     > db:0002_auto__add_field_synnefouser_new_south_test_field
268
     - Loading initial data for db.
269
    Installing json fixture 'initial_data' from '/home/bkarak/devel/synnefo/../synnefo/db/fixtures'.
270
    Installed 1 object(s) from 1 fixture(s)
271

    
272
South needs some extra definitions to the model to preserve and migrate the
273
existing data, for example, if we add a field in a model, we should declare its
274
default value. If not, South will propably fail, after indicating the error.
275

    
276
    $ ./bin/python manage.py schemamigration db --auto
277
     ? The field 'SynnefoUser.new_south_field_2' does not have a default specified, yet is NOT NULL.
278
     ? Since you are adding or removing this field, you MUST specify a default
279
     ? value to use for existing rows. Would you like to:
280
     ?  1. Quit now, and add a default to the field in models.py
281
     ?  2. Specify a one-off value to use for existing columns now
282
     ? Please select a choice: 1
283

    
284
* Data migrations:
285

    
286
If we need to do data migration as well, for example rename a field, we use tha
287
'datamigration' management command.
288

    
289
In contrast with schemamigration, to perform complex data migration, we must
290
write the script manually. The process is the following:
291

    
292
    1. Introduce the changes in the code and fixtures (initial data).
293
    2. Execute:
294

    
295
    $ ./bin/python manage.py datamigration <migration_name_here>
296

    
297
    For example:
298

    
299
    $ ./bin/python manage.py datamigration db rename_credit_wallet
300
    Created 0003_rename_credit_wallet.py.
301

    
302
    3. We edit the generated script. It contains two methods: forwards and
303
    backwards.
304

    
305
    For database operations (column additions, alter tables etc) we use the
306
    South database API (http://south.aeracode.org/docs/databaseapi.html).
307

    
308
    To access the data, we use the database reference (orm) provided as
309
    parameter in forwards, backwards method declarations in the migration
310
    script. For example:
311

    
312
    class Migration(DataMigration):
313

    
314
    def forwards(self, orm):
315
        orm.SynnefoUser.objects.all()
316

    
317
    4. To migrate the database to the latest version, we execute:
318

    
319
    ./manage.py migrate db
320

    
321
To see which migrations are applied:
322

    
323
    $ ./bin/python manage.py migrate db --list
324

    
325
      db
326
        (*) 0001_initial
327
        (*) 0002_auto__add_field_synnefouser_new_south_test_field
328
        (*) 0003_rename_credit_wallet
329

    
330
More information and more thorough examples can be found in the South web site.
331

    
332
http://south.aeracode.org/
333

    
334

    
335
UI Testing
336
----------
337
The functional ui tests require the Selenium server and the synnefo app to 
338
be running.
339

    
340
    $ wget http://selenium.googlecode.com/files/selenium-server-standalone-2.0b2.jar
341
    $ java -jar selenium-server-standalone-2.0b2.jar &
342
    $ ./bin/python manage.py runserver &
343
    $ ./bin/python manage.py test ui
344

    
345

    
346
Test coverage
347
-------------
348

    
349
In order to get code coverage reports you need to install django-test-coverage
350
   
351
   $ ./bin/pip install django-test-coverage
352

    
353
Then edit your settings.py and configure the test runner:
354

    
355
   TEST_RUNNER = 'django-test-coverage.runner.run_tests'