remove image_preference, add default_image, default_flavor to slice
[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 Controller,ControllerLinkManager,ControllerLinkDeletionManager
9 from core.models import ServiceClass
10 from core.models.serviceclass import get_default_serviceclass
11 from core.models import Tag
12 from django.contrib.contenttypes import generic
13 from core.models import Service
14 from core.models import Controller
15 from core.models import Flavor, Image
16 from django.core.exceptions import ValidationError
17
18 # Create your models here.
19
20 class Slice(PlCoreBase):
21     name = models.CharField(unique=True, help_text="The Name of the Slice", max_length=80)
22     enabled = models.BooleanField(default=True, help_text="Status for this Slice")
23     omf_friendly = models.BooleanField(default=False)
24     description=models.TextField(blank=True,help_text="High level description of the slice and expected activities", max_length=1024)
25     slice_url = models.URLField(blank=True, max_length=512)
26     site = models.ForeignKey(Site, related_name='slices', help_text="The Site this Slice belongs to")
27     max_slivers = models.IntegerField(default=10)
28     service = models.ForeignKey(Service, related_name='service', null=True, blank=True)
29     network = models.CharField(default="Private Only",null=True, blank=True, max_length=256)
30     tags = generic.GenericRelation(Tag)
31     serviceClass = models.ForeignKey(ServiceClass, related_name = "slices", null=True, default=get_default_serviceclass)
32     creator = models.ForeignKey(User, related_name='slices', blank=True, null=True)
33
34     # for tenant view
35     default_flavor = models.ForeignKey(Flavor, related_name = "slices", null=True, blank=True)
36     default_image = models.ForeignKey(Image, related_name = "slices", null=True, blank=True);
37     mount_data_sets = models.CharField(default="GenBank",null=True, blank=True, max_length=256)
38
39     def __unicode__(self):  return u'%s' % (self.name)
40
41     @property
42     def slicename(self):
43         return "%s_%s" % (self.site.login_base, self.name)
44
45     def save(self, *args, **kwds):
46         
47         site = Site.objects.get(id=self.site.id)
48         # allow preexisting slices to keep their original name for now
49         if not self.id and not self.name.startswith(site.login_base):
50             raise ValidationError('slice name must begin with %s' % site.login_base)
51         
52         if self.serviceClass is None:
53             # We allowed None=True for serviceClass because Django evolution
54             # will fail unless it is allowed. But, we we really don't want it to
55             # ever save None, so fix it up here.
56             self.serviceClass = ServiceClass.get_default()
57         if not self.creator and hasattr(self, 'caller'):
58             self.creator = self.caller
59         super(Slice, self).save(*args, **kwds)
60
61     def can_update(self, user):
62         if user.is_readonly:
63             return False
64         if user.is_admin:
65             return True
66         # slice admins can update
67         slice_privs = SlicePrivilege.objects.filter(user=user, slice=self)
68         for slice_priv in slice_privs:
69             if slice_priv.role.role == 'admin':
70                 return True
71         # site pis can update
72         site_privs = SitePrivilege.objects.filter(user=user, site=self.site)
73         for site_priv in site_privs:
74             if site_priv.role.role == 'pi':
75                 return True
76  
77         return False
78
79     @staticmethod
80     def select_by_user(user):
81         if user.is_admin:
82             qs = Slice.objects.all()
83         else:
84             # users can see slices they belong to 
85             slice_ids = [sp.slice.id for sp in SlicePrivilege.objects.filter(user=user)]
86             # pis can see slices at their sites
87             sites = [sp.site for sp in SitePrivilege.objects.filter(user=user)\
88                         if sp.role.role == 'pi']
89             slice_ids.extend([s.id for s in Slice.objects.filter(site__in=sites)]) 
90             qs = Slice.objects.filter(id__in=slice_ids)
91         return qs
92
93     def delete(self, *args, **kwds):
94         # delete networks associated with this slice
95         from core.models.network import Network
96         nets = Network.objects.filter(slices=self)
97         nets.delete() 
98         # delete slice controllers
99         slice_controllers = ControllerSlice.objects.filter(slice=self)
100         slice_controllers.delete()
101         # delete slice privilege
102         slice_privileges = SlicePrivilege.objects.filter(slice=self)
103         slice_privileges.delete() 
104         # continue with normal delete
105         super(Slice, self).delete(*args, **kwds) 
106          
107
108 class SliceRole(PlCoreBase):
109     ROLE_CHOICES = (('admin','Admin'),('default','Default'))
110
111     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
112
113     def __unicode__(self):  return u'%s' % (self.role)
114
115 class SlicePrivilege(PlCoreBase):
116     user = models.ForeignKey('User', related_name='sliceprivileges')
117     slice = models.ForeignKey('Slice', related_name='sliceprivileges')
118     role = models.ForeignKey('SliceRole',related_name='sliceprivileges')
119
120     def __unicode__(self):  return u'%s %s %s' % (self.slice, self.user, self.role)
121
122     def can_update(self, user):
123         return self.slice.can_update(user)
124
125     @staticmethod
126     def select_by_user(user):
127         if user.is_admin:
128             qs = SlicePrivilege.objects.all()
129         else:
130             sp_ids = [sp.id for sp in SlicePrivilege.objects.filter(user=user)]
131             qs = SlicePrivilege.objects.filter(id__in=sp_ids)
132         return qs
133
134 class ControllerSlice(PlCoreBase):
135     objects = ControllerLinkManager()
136     deleted_objects = ControllerLinkDeletionManager()
137
138     controller = models.ForeignKey(Controller, related_name='controllerslices')
139     slice = models.ForeignKey(Slice, related_name='controllerslices')
140     tenant_id = models.CharField(null=True, blank=True, max_length=200, help_text="Keystone tenant id")
141
142     def __unicode__(self):  return u'%s %s'  % (self.slice, self.controller)
143
144     @staticmethod
145     def select_by_user(user):
146         if user.is_admin:
147             qs = ControllerSlice.objects.all()
148         else:
149             slices = Slice.select_by_user(user)
150             qs = ControllerSlice.objects.filter(slice__in=slices)
151         return qs    
152
153     def get_cpu_stats(self):
154         filter = 'project_id=%s'%self.tenant_id
155         return monitor.get_meter('cpu',filter,None)
156
157     def get_bw_stats(self):
158         filter = 'project_id=%s'%self.tenant_id
159         return monitor.get_meter('network.outgoing.bytes',filter,None)
160
161     def get_node_stats(self):
162         return len(self.slice.slivers)