#!/usr/bin/env python # vim: set sw=4 sts=4 et : # Copyright: 2008-2009 Gentoo Foundation # Author(s): Nirbheek Chauhan # License: AGPL-3 # # Immortal lh! # from __future__ import with_statement import atexit, sys, os, shutil import os.path as osp try: from django.core import management except ImportError: print "You need to install django-1.0 first." sys.exit(1) else: if management.get_version() < '0.99': print "You need django-1.0 to use autotua-master." sys.exit(1) STAGES = ['install_master', 'syncdb_master', 'master_gpg', 'setup_sample_slave', 'slave_gpg', 'setup_sample_job'] STAGE = None ACTION = sys.argv[1] PROJDIR = 'autotua_master' RELPROJPATH = sys.argv[2] PROJPATH = osp.abspath(sys.argv[2]) SYMLINKS = True SRCDIR = osp.abspath(osp.dirname(sys.argv[0])) DATAPATH = osp.abspath(osp.join(SRCDIR, 'custom')) def print_help(): print \ """\ %(file)s: Setup the django webapp for autotua Usage: %(file)s install %(file)s syncdb Example: %(file)s install /home/me/projects/ will create `/home/me/projects/autotua_master` with all the necessary files. You then need to edit the database settings in /home/me/projects/autotua_master/settings.py After this, running %(file)s resume /home/me/projects/autotua_master will initialize the db and do other magic By default, the directory will have the files copied. Toggle `SYMLINKS` to symlink the files instead. """ % {'file': sys.argv[0]} def save_current_stage(): open(osp.join(PROJPATH, '.last_stage'), 'w').write(STAGE) def next_stage(): global STAGE next_stage_index = STAGES.index(STAGE)+1 if next_stage_index < len(STAGES): STAGE = STAGES[next_stage_index] else: all_done() def resume_last_stage(): global STAGE stages = None if STAGE == STAGES[0]: stages = [STAGE] else: with open(osp.join(PROJPATH, '.last_stage'), 'r') as last_stage: STAGE = last_stage.read().rstrip('\n') # If we're at the last stage if STAGE == STAGES[-1]: all_done() stages = STAGES[STAGES.index(STAGE):] # For each stage since last_stage for stage in stages: eval('%s()' % stage) next_stage() def install_master(): """Start the new project""" import subprocess # Need to be in the project's parent dir os.chdir(osp.dirname(PROJPATH)) print os.getcwd(), PROJPATH management.call_command('startproject', osp.basename(PROJPATH)) if SYMLINKS: os.symlink(osp.join(SRCDIR, 'master'), osp.join(PROJPATH, 'master')) for file in ['urls.py']: dest_file = osp.join(PROJPATH, file) if osp.isfile(dest_file): os.remove(dest_file) os.symlink(osp.join(DATAPATH, file), dest_file) else: shutil.copytree(osp.join(SRCDIR, 'master'), osp.join(PROJPATH, 'master')) for file in ['urls.py']: shutil.copy(osp.join(DATAPATH, file), PROJPATH) settings = open(osp.join(PROJPATH, 'settings.py'), 'a') master_settings = open(osp.join(DATAPATH, 'merge_settings.py')) settings.write('\n'+master_settings.read()) settings.close() master_settings.close() print """ =================================== Setup done. Now you need to edit the database settings in %(dest)s/settings.py and run `./setup-master.py resume %(dest)s` =================================== """ % { 'dest': RELPROJPATH } def syncdb_master(): """Initialize the database""" import copy # Database defaults from db_defaults import groups, providers, archs, releases, mirrors # Django project settings import settings from django.core.management import setup_environ setup_environ(settings) from master.models import Group, Arch, Provider, Release, Mirror # Need to be in the project dir os.chdir(PROJPATH) management.call_command('syncdb') # User-related defaults for group in groups: Group(name=group).save() # Job-related defaults for (gen_arch, spec_archs) in archs.iteritems(): gen_archobj = Arch(generic=gen_arch) for spec_arch in spec_archs: archobj = copy.copy(gen_archobj) archobj.specific = spec_arch archobj.save() # Populate providers for provider in providers: provobj = Provider(name=provider) provobj.save() # Populate release list releaseobj = Release(provider=provobj) for (release, relarchs) in releases[provider].iteritems(): relobj = copy.copy(releaseobj) relobj.name = release relobj.save() for (relgen_arch, relspec_archs) in relarchs.iteritems(): for relspec_arch in relspec_archs: relobj.archs.add(Arch.objects.get(generic=relgen_arch, specific=relspec_arch)) # Populate mirror list obj = Mirror(owner=provobj) obj.structure = mirrors[provider]['structure'] for server in mirrors[provider]['servers']: serverobj = copy.copy(obj) serverobj.server = server[0] serverobj.prefix = server[1] serverobj.save() def setup_gpg(data, gpghome): from autotua import crypt if not osp.isdir(gpghome): os.mkdir(gpghome, 0700) print 'Creating a "sample" gpg key (expires in 1 month)' crypt.Crypto(gpghome).init_gpghome(**data) def master_gpg(): from master import const from sample_data import sample_master_gpg_data setup_gpg(sample_master_gpg_data, const.GPGHOME) def slave_gpg(): from master import const from sample_data import sample_slave_gpg_data setup_gpg(sample_slave_gpg_data, osp.join(const.MASTER_DIR, 'sample_slave_gpghome')) def setup_sample_slave(): # Sample data for slave from sample_data import sample_slave # Django project settings import settings from django.core.management import setup_environ setup_environ(settings) from master import const from master.models import User, Group, Provider, Arch, Release, Mirror, Job, Slave # Need to be in the project dir os.chdir(PROJPATH) slave = Slave() slave.name = sample_slave['name'] try: slave.owner = User.objects.get(username=sample_slave['owner']['username']) except User.DoesNotExist: slave.owner = User.objects.create_user(*[sample_slave['owner'][key] for key in ('username', 'email', 'password')]) slave.owner.groups.add(Group.objects.get(name=sample_slave['owner']['group'])) slave.save() slave.users = [Group.objects.get(name=group) for group in sample_slave['users']] slave.save() def setup_sample_job(): from autotua import sync # Sample data for master from sample_data import sample_job # Django project settings import settings from django.core.management import setup_environ setup_environ(settings) from master.models import User, Provider, Release, Job, Slave # Setup the jobtage tree in /var/tmp/autotua/jobtage sync.Syncer().sync() # Need to be in the project dir os.chdir(PROJPATH) # Get on with the job at hand... ;) job = Job() for i in ['name', 'jobtagerev', 'atoms']: setattr(job, i, sample_job[i]) job.name = sample_job['name'] job.maintainer = User.objects.get(username=sample_job['maintainer']['username']) job.release = Release.objects.get(name=sample_job['release'], provider=Provider.objects.get(name=sample_job['provider'])) job.arch = job.release.archs.get(specific=sample_job['arch']) # If stage is not set, defaults to stage3 job.save() job.slaves.add(Slave.objects.get(name=sample_job['slave'])) job.save() def all_done(): print "All done! Now you can start the master with `python manage.py runserver`" sys.exit() ################ ## Parse Args ## ################ if len(sys.argv) < 3: print "Insufficient arguments:" print_help() sys.exit(1) if ACTION == 'install': PROJPATH = osp.join(PROJPATH, PROJDIR) STAGE = 'install_master' if not osp.isdir(osp.dirname(PROJPATH)): os.makedirs(osp.dirname(PROJPATH)) elif ACTION == 'path-install': STAGE = 'install_master' if not osp.isdir(osp.dirname(PROJPATH)): os.makedirs(osp.dirname(PROJPATH)) elif ACTION == 'resume': pass else: print_help() sys.exit(1) ####################### ## Setup search path ## ####################### # XXX: Document this in the help if os.environ.has_key('PYTHONPATH'): sys.path.insert(0, os.environ['PYTHONPATH']) # Remove current directory from search path sys.path = sys.path[1:] sys.path.append(SRCDIR) sys.path.append(DATAPATH) sys.path.append(PROJPATH) #################### ## Start our work ## #################### atexit.register(save_current_stage) resume_last_stage()