diff options
author | Nirbheek Chauhan <nirbheek.chauhan@gmail.com> | 2008-09-01 00:57:27 +0530 |
---|---|---|
committer | Nirbheek Chauhan <nirbheek.chauhan@gmail.com> | 2008-09-01 00:57:27 +0530 |
commit | 454ab865118f561c1e04b663f63131828996e1a0 (patch) | |
tree | 5d483990a559226529b0cddf059e1412e3a8f8d2 | |
parent | Model validation was removed for django 1.0 (diff) | |
download | autotua-454ab865118f561c1e04b663f63131828996e1a0.tar.gz autotua-454ab865118f561c1e04b663f63131828996e1a0.tar.bz2 autotua-454ab865118f561c1e04b663f63131828996e1a0.zip |
Major changes to the master django db models
- Stages, Archs, Releases, Mirrors (and structure), Providers (distros)
are represented by models.Model classes.
* This allows them to be updated without a webapp restart
* Will allow (in the future) per-user definitions as well
* Makes validation, pre-save manipulation, and form input much, *much* easier
* Modify process/* accordingly
- validation.py is now redundant, kill it
- The ARCHS, STAGES etc. definitions are still around; they will be
moved to setup-master.py for an initial database initialization
- Add a basic (untested) ModelForm form JobForm
- Add a stub Slave(models.Model) class
-rw-r--r-- | master/autotua/models.py | 153 | ||||
-rw-r--r-- | master/autotua/process/__init__.py | 50 | ||||
-rw-r--r-- | master/autotua/process/const.py | 5 | ||||
-rw-r--r-- | master/autotua/process/validate.py | 34 |
4 files changed, 148 insertions, 94 deletions
diff --git a/master/autotua/models.py b/master/autotua/models.py index c225712..a2d93cc 100644 --- a/master/autotua/models.py +++ b/master/autotua/models.py @@ -7,30 +7,110 @@ # from django.db import models +from django.forms import ModelForm, ModelChoiceField from django.contrib.auth.models import User -import process +from autotua import jobuild, sync + +#################### +### Models begin ### +#################### +class StageProvider(models.Model): + # Identifier for the stage provider. + # Ex: 'gentoo', 'funtoo', 'gentooexperimental' + name = models.CharField(max_length=25, unique=True) + + def __unicode__(self): + return self.name + +class Stage(models.Model): + # stage{1,2,3,4} etc + name = models.CharField(max_length=25) + # Stage provider that supports this stage + provider = models.ForeignKey(StageProvider) + + class Meta: + unique_together = ['name', 'provider'] + + def __unicode__(self): + return '%s (%s)' % (self.stage, self.provider.name) + +class Arch(models.Model): + # Specific arch i686, g4, ~amd64, core32 etc. + specific = models.CharField(max_length=25) + # The generic arch corresponding to the above specific arch + # Ex: 'specific': 'i686', 'generic': 'x86' + # This is needed for Gentoo mirrors + generic = models.CharField(max_length=25, blank=True) + # Stage provider that supports stages with this arch + provider = models.ForeignKey(StageProvider) + + class Meta: + unique_together = ['specific', 'provider'] + + def __unicode__(self): + return '%s (%s)' % (self.arch, self.provider.name) + +class Release(models.Model): + # Release number/identifier + name = models.CharField(max_length=25) + # Release provider + provider = models.ForeignKey(StageProvider) + + class Meta: + unique_together = ['name', 'provider'] + + def __unicode__(self): + return '%s (%s)' % (self.release, self.provider.name) + +class Mirror(models.Model): + # Mirror owner + owner = models.ForeignKey(StageProvider) + # Mirror root URL + # Ex: 'http://gentoo.osousl.org/', 'http://www.funtoo.org/' + server = models.URLField() + # Prefix to the stage file structure root + # Ex: 'releases/', 'linux/' + prefix = models.CharField(max_length=25) + # How to get a URI for a stage file by putting in various variables + # Ex: Gentoo mirrors are structured as follows: + # '%(gen_arch)s/%(release)s/stages/%(stage)s-%(arch)s-%(release)s.tar.bz2' + # Funtoo is structured as follows: + # '%(arch)s/%(owner)s-%(arch)s-%(release)/%(stage)s-%(arch)s-%(release)s.tar.bz2' + structure = models.CharField(max_length=200) + + class Meta: + unique_together = ['server', 'prefix'] + + def __unicode__(self): + return '%s/%s (%s)' % (self.server, self.prefix, self.owner.name) + + def save(self): + if not self.server.endswith('/'): + self.server += '/' + if not self.prefix.endswith('/'): + self.prefix += '/' + super(Mirror, self).save() -# Create your models here. class Job(models.Model): # Identifier for the job - name = models.CharField(max_length=30, unique=True) + name = models.CharField(max_length=30, + help_text="Identifier for the job") # Name of maintainer - maintainer = models.ForeignKey(User) - # gentoo://stage{1..4} or URL - # Using a URL => stage, arch, type, release ignored - stage = models.CharField(max_length=25) + maintainer = models.ForeignKey(User, editable=False) + # Stage provider + provider = models.ForeignKey(StageProvider) + # Stage type + stage = models.ForeignKey(Stage) # i686, amd64, g4, etc. - arch = models.CharField(max_length=25) + arch = models.ForeignKey(Arch) + # Release + release = models.ForeignKey(Release) # Type of stage; hardened, uclibc, etc #type = CharField(maxlength=25) # const.stage_types - # List of releases? - release = models.CharField(max_length=25) # Revision of jobtage tree to use (not to be entered by user) - jobtagerev = models.CharField(max_length=50) + jobtagerev = models.CharField(max_length=50, editable=False) # Root jobuild atom; auto-converted to deplist atoms = models.TextField() - # Status of job - #status = models.BooleanField() class Meta: unique_together = [("name", "maintainer")] @@ -39,7 +119,52 @@ class Job(models.Model): return '%s/%s' % (self.maintainer, self.name) def save(self): - atoms = process._get_deplist(self.atoms.split(), self.jobtagerev) + atoms = self._get_deplist(self.atoms.split(), self.jobtagerev) print atoms self.atoms = '\n'.join(atoms) super(Job, self).save() + + def _get_deplist(atoms, rev): + """ + Use autotua-slave to get the deplist + from the root jobuild atom + + Support multiple atoms for the multiple-save case + """ + # FIXME: Re-implement using git-fuse? + jobtagedir = '%s/jobtage-%s' % (const.TMPDIR, random.randint(0, 99999)) + sync.Syncer(scheme='git-export', uri=const.JOBTAGE, destdir=jobtagedir).sync() + + deplist = [] + for atom in atoms: + resolver = jobuild.Resolver(jobuild.Jobuild(jobtagedir, atom)) + deplist.extend(resolver.resolve()) + deplist.reverse() + # Fake jobuild.Resolver to get at _unique ;p + return jobuild.Resolver(None)._unique(deplist) + +class Slave(models.Model): + # Which user owns this slave + owner = models.ForeignKey(User) + # Status of slave + #status = models.ForeignKey(Job) + +################### +### Forms begin ### +################### +class JobForm(ModelForm): + # FIXME: Make the default here as 'gentoo' once db is populated. + provider = ModelChoiceField(label="Stage Provider", + queryset=StageProvider.objects.all()) + # FIXME FIXME FIXME: All fields after this should filter on the + #basis of the above specified provider. + # Javascript? Two steps for form submission? + stage = ModelChoiceField(label="Stage type", + queryset=Stage.objects.all()) + arch = ModelChoiceField(label="Arch", + queryset=Arch.objects.all()) + release = ModelChoiceField(label="Release", + queryset=Release.objects.all()) + class Meta: + model = Job + include = ('name', 'atoms') diff --git a/master/autotua/process/__init__.py b/master/autotua/process/__init__.py index 75d86b3..e118d54 100644 --- a/master/autotua/process/__init__.py +++ b/master/autotua/process/__init__.py @@ -7,47 +7,15 @@ # import random -from autotua import jobuild, sync - -schemes = ['http', 'https', 'ftp'] +from ..models import Mirror def generate_stage_url(job): - scheme, stage = job.stage.split('://', 1) - if scheme in schemes: - return job.stage - else: - job.stage = stage - job.gen_arch = _get_arch_dir(job.arch) - job.mirror = random.choice(const.MIRRORS[scheme]) - url = const.STAGE_URI % job.__dict__ + mirror = random.choice(Mirror.objects.list(owner=job.provider)) + url = mirror.server+mirror.prefix+mirror.structure + data['owner'] = mirror.owner.name + data['stage'] = job.stage.name + data['arch'] = job.arch.specific + data['gen_arch'] = job.arch.generic + data['release'] = job.release.name + url = url % data return url - -def _get_arch_dir(arch): - """ - Convert specific archs to generic archs - i686 -> x86 - mips4 -> mips - """ - for i in const.ARCHS: - if arch in const.ARCHS[i]: - return i - raise Exception(const.VERRORS['invalid_arch'] % i) - -def _get_deplist(atoms, rev): - """ - Use autotua-slave to get the deplist - from the root jobuild atom - - Support multiple atoms for the multiple-save case - """ - # FIXME: Re-implement using git-fuse? - jobtagedir = '%s/jobtage-%s' % (const.TMPDIR, random.randint(0, 99999)) - sync.Syncer(scheme='git-export', uri=const.JOBTAGE, destdir=jobtagedir).sync() - - deplist = [] - for atom in atoms: - resolver = jobuild.Resolver(jobuild.Jobuild(jobtagedir, atom)) - deplist.extend(resolver.resolve()) - # jobuild.Resolver._unique() reverses the list; hence reverse in advance - deplist.reverse() - return jobuild.Resolver(None)._unique(deplist) # Fake jobuild.Resolver to get at _unique ;p diff --git a/master/autotua/process/const.py b/master/autotua/process/const.py index 98c74f8..9df0f5b 100644 --- a/master/autotua/process/const.py +++ b/master/autotua/process/const.py @@ -34,8 +34,3 @@ MIRRORS = { 'gentoo': ('http://gentoo.osuosl.org',) } STAGES = ('stage1', 'stage2', 'stage3', 'stage4',) STAGE_URI = '%(mirror)s/releases/%(gen_arch)s/%(release)s/stages/%(stage)s-%(arch)s-%(release)s.tar.bz2' #stage_types = ('', 'hardened', 'hardened+nomultilib') - -VERRORS = { 'invalid_stage': 'Invalid stage: %s', - 'invalid_arch': 'Invalid arch: %s', - 'invalid_type': 'Invalid type: %s', - 'invalid_release': 'Invalid release: %s' } diff --git a/master/autotua/process/validate.py b/master/autotua/process/validate.py deleted file mode 100644 index dcbc201..0000000 --- a/master/autotua/process/validate.py +++ /dev/null @@ -1,34 +0,0 @@ -# vim: set sw=4 sts=4 et : -# Copyright: 2008 Gentoo Foundation -# Author(s): Nirbheek Chauhan <nirbheek.chauhan@gmail.com> -# License: GPL-2 -# -# Immortal lh! -# - -from datetime import datetime -import const - -def is_stage(stage): - if stage not in const.STAGES: - raise Exception(const.VERRORS['invalid_stage'] % stage) - return True - -def is_arch(arch): - if arch not in const.ARCHS['all']: - raise Exception(const.VERRORS['invalid_arch'] % i) - return True - -def is_type(type): - if type not in const.STAGE_TYPE: - raise Exception(const.VERRORS['invalid_type'] % type) - return True - -def is_release(release): - year, state = release.split('_', 1) - try: - if int(year.split('.', 1)[0]) > datetime.now().year: - raise Exception(const.VERRORS['invalid_release'] % release) - except: - raise Exception(const.VERRORS['invalid_release'] % release) - return True |