aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNirbheek Chauhan <nirbheek.chauhan@gmail.com>2008-09-01 00:57:27 +0530
committerNirbheek Chauhan <nirbheek.chauhan@gmail.com>2008-09-01 00:57:27 +0530
commit454ab865118f561c1e04b663f63131828996e1a0 (patch)
tree5d483990a559226529b0cddf059e1412e3a8f8d2
parentModel validation was removed for django 1.0 (diff)
downloadautotua-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.py153
-rw-r--r--master/autotua/process/__init__.py50
-rw-r--r--master/autotua/process/const.py5
-rw-r--r--master/autotua/process/validate.py34
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