Controller.backend_type is required
[plstackapi.git] / planetstack / core / models / site.py
1 import os
2 from django.db import models
3 from django.db.models import Q
4 from core.models import PlCoreBase,PlCoreBaseManager,PlCoreBaseDeletionManager
5 from core.models import Tag
6 from django.contrib.contenttypes import generic
7 from geoposition.fields import GeopositionField
8 from core.acl import AccessControlList
9 from planetstack.config import Config
10
11 config = Config()
12
13 class ControllerLinkDeletionManager(PlCoreBaseDeletionManager):
14     def get_queryset(self):
15         parent=super(ControllerLinkDeletionManager, self)
16         try:
17             backend_type = config.observer_backend_type
18         except AttributeError:
19             backend_type = None
20
21         parent_queryset = parent.get_queryset() if hasattr(parent, "get_queryset") else parent.get_query_set()
22         if (backend_type):
23             return parent_queryset.filter(Q(controller__backend_type=backend_type))
24         else:
25             return parent_queryset
26
27     # deprecated in django 1.7 in favor of get_queryset().
28     def get_query_set(self):
29         return self.get_queryset()
30
31
32 class ControllerDeletionManager(PlCoreBaseDeletionManager):
33     def get_queryset(self):
34         parent=super(ControllerDeletionManager, self)
35
36         try:
37             backend_type = config.observer_backend_type
38         except AttributeError:
39             backend_type = None
40
41         parent_queryset = parent.get_queryset() if hasattr(parent, "get_queryset") else parent.get_query_set()
42
43         if backend_type:
44             return parent_queryset.filter(Q(backend_type=backend_type))
45         else:
46             return parent_queryset
47
48     # deprecated in django 1.7 in favor of get_queryset().
49     def get_query_set(self):
50         return self.get_queryset()
51
52 class ControllerLinkManager(PlCoreBaseManager):
53     def get_queryset(self):
54         parent=super(ControllerLinkManager, self)
55
56         try:
57             backend_type = config.observer_backend_type
58         except AttributeError:
59             backend_type = None
60
61         parent_queryset = parent.get_queryset() if hasattr(parent, "get_queryset") else parent.get_query_set()
62
63         if backend_type:
64             return parent_queryset.filter(Q(controller__backend_type=backend_type))
65         else:
66             return parent_queryset
67
68     # deprecated in django 1.7 in favor of get_queryset().
69     def get_query_set(self):
70         return self.get_queryset()
71
72
73 class ControllerManager(PlCoreBaseManager):
74     def get_queryset(self):
75         parent=super(ControllerManager, self)
76
77         try:
78             backend_type = config.observer_backend_type
79         except AttributeError:
80             backend_type = None
81
82         parent_queryset = parent.get_queryset() if hasattr(parent, "get_queryset") else parent.get_query_set()
83
84         if backend_type:
85             return parent_queryset.filter(Q(backend_type=backend_type))
86         else:
87             return parent_queryset
88
89     # deprecated in django 1.7 in favor of get_queryset().
90     def get_query_set(self):
91         return self.get_queryset()
92
93 class Site(PlCoreBase):
94     """
95         A logical grouping of Nodes that are co-located at the same geographic location, which also typically corresponds to the Nodes' location in the physical network.
96     """
97     name = models.CharField(max_length=200, help_text="Name for this Site")
98     site_url = models.URLField(null=True, blank=True, max_length=512, help_text="Site's Home URL Page")
99     enabled = models.BooleanField(default=True, help_text="Status for this Site")
100     location = GeopositionField()
101     longitude = models.FloatField(null=True, blank=True)
102     latitude = models.FloatField(null=True, blank=True)
103     login_base = models.CharField(max_length=50, unique=True, help_text="Prefix for Slices associated with this Site")
104     is_public = models.BooleanField(default=True, help_text="Indicates the visibility of this site to other members")
105     abbreviated_name = models.CharField(max_length=80)
106
107     #deployments = models.ManyToManyField('Deployment', blank=True, related_name='sites')
108     deployments = models.ManyToManyField('Deployment', through='SiteDeployment', blank=True, help_text="Select which sites are allowed to host nodes in this deployment", related_name='sites')
109     tags = generic.GenericRelation(Tag)
110
111     def __unicode__(self):  return u'%s' % (self.name)
112
113     def can_update(self, user):
114         if user.is_readonly:
115             return False
116         if user.is_admin:
117             return True
118         site_privs = SitePrivilege.objects.filter(user=user, site=self)
119         for site_priv in site_privs:
120             if site_priv.role.role == 'pi':
121                 return True
122         return False 
123
124     @staticmethod
125     def select_by_user(user):
126         if user.is_admin:
127             qs = Site.objects.all()
128         else:
129             site_ids = [sp.site.id for sp in SitePrivilege.objects.filter(user=user)]
130             site_ids.append(user.site.id)
131             qs = Site.objects.filter(id__in=site_ids)
132         return qs
133
134
135 class SiteRole(PlCoreBase):
136
137     ROLE_CHOICES = (('admin','Admin'),('pi','PI'),('tech','Tech'),('billing','Billing'))
138     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
139
140     def __unicode__(self):  return u'%s' % (self.role)
141
142 class SitePrivilege(PlCoreBase):
143
144     user = models.ForeignKey('User', related_name='siteprivileges')
145     site = models.ForeignKey('Site', related_name='siteprivileges')
146     role = models.ForeignKey('SiteRole',related_name='siteprivileges')
147
148     def __unicode__(self):  return u'%s %s %s' % (self.site, self.user, self.role)
149
150     def save(self, *args, **kwds):
151         super(SitePrivilege, self).save(*args, **kwds)
152
153     def delete(self, *args, **kwds):
154         super(SitePrivilege, self).delete(*args, **kwds)
155
156     def can_update(self, user):
157         return self.site.can_update(user)
158
159     @staticmethod
160     def select_by_user(user):
161         if user.is_admin:
162             qs = SitePrivilege.objects.all()
163         else:
164             sp_ids = [sp.id for sp in SitePrivilege.objects.filter(user=user)]
165             qs = SitePrivilege.objects.filter(id__in=sp_ids)
166         return qs
167
168 class Deployment(PlCoreBase):
169     #objects = Controllermanager()
170     #deleted_objects = DeploymentDeletionManager()
171     name = models.CharField(max_length=200, unique=True, help_text="Name of the Deployment")
172     #admin_user = models.CharField(max_length=200, null=True, blank=True, help_text="Username of an admin user at this deployment")
173     #admin_password = models.CharField(max_length=200, null=True, blank=True, help_text="Password of theadmin user at this deployment")\r
174     #admin_tenant = models.CharField(max_length=200, null=True, blank=True, help_text="Name of the tenant the admin user belongs to")\r
175     #auth_url = models.CharField(max_length=200, null=True, blank=True, help_text="Auth url for the deployment")
176     #backend_type = models.CharField(max_length=200, null=True, blank=True, help_text="Type of deployment, e.g. EC2, OpenStack, or OpenStack version")
177     #availability_zone = models.CharField(max_length=200, null=True, blank=True, help_text="OpenStack availability zone")
178
179     # smbaker: the default of 'allow all' is intended for evolutions of existing
180     #    deployments. When new deployments are created via the GUI, they are
181     #    given a default of 'allow site <site_of_creator>'
182     accessControl = models.TextField(max_length=200, blank=False, null=False, default="allow all",
183                                      help_text="Access control list that specifies which sites/users may use nodes in this deployment")
184
185     def get_acl(self):
186         return AccessControlList(self.accessControl)
187
188     def test_acl(self, slice=None, user=None):
189         potential_users=[]
190
191         if user:
192             potential_users.append(user)
193
194         if slice:
195             potential_users.append(slice.creator)
196             for priv in slice.sliceprivileges.all():
197                 if priv.user not in potential_users:
198                     potential_users.append(priv.user)
199
200         acl = self.get_acl()
201         for user in potential_users:
202             if acl.test(user) == "allow":
203                 return True
204
205         return False
206
207     @staticmethod
208     def select_by_acl(user):
209         ids = []
210         for deployment in Deployment.objects.all():
211             acl = deployment.get_acl()
212             if acl.test(user) == "allow":
213                 ids.append(deployment.id)
214
215         return Deployment.objects.filter(id__in=ids)
216
217     def __unicode__(self):  return u'%s' % (self.name)
218
219 class DeploymentRole(PlCoreBase):
220     #objects = DeploymentLinkManager()
221     #deleted_objects = DeploymentLinkDeletionManager()
222     ROLE_CHOICES = (('admin','Admin'),)
223     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
224
225     def __unicode__(self):  return u'%s' % (self.role)
226
227 class DeploymentPrivilege(PlCoreBase):
228     #objects = DeploymentLinkManager()
229     #deleted_objects = DeploymentLinkDeletionManager()
230
231     user = models.ForeignKey('User', related_name='deploymentprivileges')
232     deployment = models.ForeignKey('Deployment', related_name='deploymentprivileges')
233     role = models.ForeignKey('DeploymentRole',related_name='deploymentprivileges')
234
235     def __unicode__(self):  return u'%s %s %s' % (self.deployment, self.user, self.role)
236
237     def can_update(self, user):
238         if user.is_readonly:
239             return False
240         if user.is_admin:
241             return True
242         dprivs = DeploymentPrivilege.objects.filter(user=user)
243         for dpriv in dprivs:
244             if dpriv.role.role == 'admin':
245                 return True
246         return False
247
248     @staticmethod
249     def select_by_user(user):
250         if user.is_admin:
251             qs = DeploymentPrivilege.objects.all()
252         else:
253             dpriv_ids = [dp.id for dp in DeploymentPrivilege.objects.filter(user=user)]
254             qs = DeploymentPrivilege.objects.filter(id__in=dpriv_ids)
255         return qs
256
257 class ControllerRole(PlCoreBase):
258     #objects = ControllerLinkManager()
259     #deleted_objects = ControllerLinkDeletionManager()
260
261     ROLE_CHOICES = (('admin','Admin'),)
262     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
263
264     def __unicode__(self):  return u'%s' % (self.role)
265
266 class Controller(PlCoreBase):
267
268     objects = ControllerManager()
269     deleted_objects = ControllerDeletionManager()
270
271     name = models.CharField(max_length=200, unique=True, help_text="Name of the Controller")
272     backend_type = models.CharField(max_length=200, help_text="Type of compute controller, e.g. EC2, OpenStack, or OpenStack version")
273     version = models.CharField(max_length=200, help_text="Controller version")
274     auth_url = models.CharField(max_length=200, null=True, blank=True, help_text="Auth url for the compute controller")
275     admin_user = models.CharField(max_length=200, null=True, blank=True, help_text="Username of an admin user at this controller")
276     admin_password = models.CharField(max_length=200, null=True, blank=True, help_text="Password of theadmin user at this controller")
277     admin_tenant = models.CharField(max_length=200, null=True, blank=True, help_text="Name of the tenant the admin user belongs to")
278
279     def __unicode__(self):  return u'%s %s %s' % (self.name, self.backend_type, self.version)
280
281     def can_update(self, user):
282         if user.is_readonly:
283             return False
284         if user.is_admin:
285             return True
286         return False
287
288 class SiteDeployment(PlCoreBase):
289     objects = ControllerLinkManager()
290     deleted_objects = ControllerLinkDeletionManager()
291
292     site = models.ForeignKey(Site,related_name='sitedeployments')
293     deployment = models.ForeignKey(Deployment,related_name='sitedeployments')
294     controller = models.ForeignKey(Controller, null=True, blank=True, related_name='sitedeployments')
295     availability_zone = models.CharField(max_length=200, null=True, blank=True, help_text="OpenStack availability zone")
296
297     def __unicode__(self):  return u'%s %s' % (self.deployment, self.site)
298     
299 class ControllerSite(PlCoreBase):
300      
301     site = models.ForeignKey(Site,related_name='controllersite')
302     controller = models.ForeignKey(Controller, null=True, blank=True, related_name='controllersite')
303     tenant_id = models.CharField(null=True, blank=True, max_length=200, db_index=True, help_text="Keystone tenant id")