Merge branch 'master' of ssh://git.planet-lab.org/git/plstackapi
[plstackapi.git] / planetstack / core / models / slice.py
1 import os
2 from django.db import models
3 from core.models import PlCoreBase
4 from core.models import Site
5 from core.models.site import SitePrivilege
6 from core.models import User
7 from core.models import Role
8 from core.models import Deployment
9 from core.models import ServiceClass
10 from core.models import Tag
11 from django.contrib.contenttypes import generic
12 from core.models import Service
13 from core.models import Deployment
14 from django.core.exceptions import ValidationError
15
16 # Create your models here.
17
18 class Slice(PlCoreBase):
19     name = models.CharField(unique=True, help_text="The Name of the Slice", max_length=80)
20     enabled = models.BooleanField(default=True, help_text="Status for this Slice")
21     omf_friendly = models.BooleanField()
22     description=models.TextField(blank=True,help_text="High level description of the slice and expected activities", max_length=1024)
23     slice_url = models.URLField(blank=True, max_length=512)
24     site = models.ForeignKey(Site, related_name='slices', help_text="The Site this Slice belongs to")
25     max_slivers = models.IntegerField(default=10) 
26     imagePreference = models.CharField(default="Ubuntu 12.04 LTS", null=True, blank=True, max_length=256)
27     service = models.ForeignKey(Service, related_name='service', null=True, blank=True)
28     network = models.CharField(default="Private Only",null=True, blank=True, max_length=256)
29     mountDataSets = models.CharField(default="GenBank",null=True, blank=True, max_length=256)
30     tags = generic.GenericRelation(Tag)
31
32     serviceClass = models.ForeignKey(ServiceClass, related_name = "slices", null=True, default=ServiceClass.get_default)
33     creator = models.ForeignKey(User, related_name='slices', blank=True, null=True)
34
35     def __unicode__(self):  return u'%s' % (self.name)
36
37     @property
38     def slicename(self):
39         return "%s_%s" % (self.site.login_base, self.name)
40
41     def save(self, *args, **kwds):
42         
43         site = Site.objects.get(id=self.site.id)
44         if not self.name.startswith(site.login_base):
45             raise ValidationError('slice name must begin with %s' % site.login_base)
46         
47         if self.serviceClass is None:
48             # We allowed None=True for serviceClass because Django evolution
49             # will fail unless it is allowed. But, we we really don't want it to
50             # ever save None, so fix it up here.
51             self.serviceClass = ServiceClass.get_default()
52         if not self.creator and hasattr(self, 'caller'):
53             self.creator = self.caller
54         super(Slice, self).save(*args, **kwds)
55
56     def can_update(self, user):
57         if user.is_readonly:
58             return False
59         if user.is_admin:
60             return True
61         # slice admins can update
62         slice_privs = SlicePrivilege.objects.filter(user=user, slice=self)
63         for slice_priv in slice_privs:
64             if slice_priv.role.role == 'admin':
65                 return True
66         # site pis can update
67         site_privs = SitePrivilege.objects.filter(user=user, site=self.site)
68         for site_priv in site_privs:
69             if site_priv.role.role == 'pi':
70                 return True
71  
72         return False
73
74     @staticmethod
75     def select_by_user(user):
76         if user.is_admin:
77             qs = Slice.objects.all()
78         else:
79             # users can see slices they belong to 
80             slice_ids = [sp.slice.id for sp in SlicePrivilege.objects.filter(user=user)]
81             # pis can see slices at their sites
82             sites = [sp.site for sp in SitePrivilege.objects.filter(user=user)\
83                         if sp.role.role == 'pi']
84             slice_ids.extend([s.id for s in Slice.objects.filter(site__in=sites)]) 
85             qs = Slice.objects.filter(id__in=slice_ids)
86         return qs
87
88 class SliceRole(PlCoreBase):
89     ROLE_CHOICES = (('admin','Admin'),('default','Default'))
90
91     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
92
93     def __unicode__(self):  return u'%s' % (self.role)
94
95 class SlicePrivilege(PlCoreBase):
96     user = models.ForeignKey('User', related_name='slice_privileges')
97     slice = models.ForeignKey('Slice', related_name='slice_privileges')
98     role = models.ForeignKey('SliceRole')
99
100     def __unicode__(self):  return u'%s %s %s' % (self.slice, self.user, self.role)
101
102     def can_update(self, user):
103         return self.slice.can_update(user)
104
105     @staticmethod
106     def select_by_user(user):
107         if user.is_admin:
108             qs = SlicePrivilege.objects.all()
109         else:
110             sp_ids = [sp.id for sp in SlicePrivilege.objects.filter(user=user)]
111             qs = SlicePrivilege.objects.filter(id__in=sp_ids)
112         return qs
113
114 class SliceDeployments(PlCoreBase):
115     slice = models.ForeignKey(Slice)
116     deployment = models.ForeignKey(Deployment)
117     tenant_id = models.CharField(null=True, blank=True, max_length=200, help_text="Keystone tenant id")
118     network_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum network")
119     router_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum router id")
120     subnet_id = models.CharField(null=True, blank=True, max_length=256, help_text="Quantum subnet id")
121
122     def __unicode__(self):  return u'%s %s'  % (self.slice, self.deployment)
123
124     @staticmethod
125     def select_by_user(user):
126         if user.is_admin:
127             qs = SliceDeployments.objects.all()
128         else:
129             slices = Slice.select_by_user(user)
130             qs = SliceDeployments.objects.filter(slice__in=slices)
131         return qs