For backend-specific observers, filter out deployments without backend
[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 DeploymentLinkDeletionManager(PlCoreBaseDeletionManager):
14     def get_queryset(self):
15         parent=super(DeploymentLinkDeletionManager, 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(deployment__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 DeploymentDeletionManager(PlCoreBaseDeletionManager):
33     def get_queryset(self):
34         parent=super(DeploymentDeletionManager, 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 DeploymentLinkManager(PlCoreBaseManager):
53     def get_queryset(self):
54         parent=super(DeploymentLinkManager, 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(deployment__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 DeploymentManager(PlCoreBaseManager):
74     def get_queryset(self):
75         parent=super(DeploymentManager, 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='SiteDeployments', 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='site_privileges')
145     site = models.ForeignKey('Site', related_name='site_privileges')
146     role = models.ForeignKey('SiteRole')
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 = DeploymentManager()
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.slice_privileges.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
223     ROLE_CHOICES = (('admin','Admin'),)
224     role = models.CharField(choices=ROLE_CHOICES, unique=True, max_length=30)
225
226     def __unicode__(self):  return u'%s' % (self.role)
227
228 class DeploymentPrivilege(PlCoreBase):
229     objects = DeploymentLinkManager()
230     deleted_objects = DeploymentLinkDeletionManager()
231
232     user = models.ForeignKey('User', related_name='deployment_privileges')
233     deployment = models.ForeignKey('Deployment', related_name='deployment_privileges')
234     role = models.ForeignKey('DeploymentRole')
235
236     def __unicode__(self):  return u'%s %s %s' % (self.deployment, self.user, self.role)
237
238     def can_update(self, user):
239         if user.is_readonly:
240             return False
241         if user.is_admin:
242             return True
243         dprivs = DeploymentPrivilege.objects.filter(user=user)
244         for dpriv in dprivs:
245             if dpriv.role.role == 'admin':
246                 return True
247         return False
248
249     @staticmethod
250     def select_by_user(user):
251         if user.is_admin:
252             qs = DeploymentPrivilege.objects.all()
253         else:
254             dpriv_ids = [dp.id for dp in DeploymentPrivilege.objects.filter(user=user)]
255             qs = DeploymentPrivilege.objects.filter(id__in=dpriv_ids)
256         return qs 
257
258 class SiteDeployments(PlCoreBase):
259     objects = DeploymentLinkManager()
260     deleted_objects = DeploymentLinkDeletionManager()
261
262     site = models.ForeignKey(Site)
263     deployment = models.ForeignKey(Deployment)
264     tenant_id = models.CharField(null=True, blank=True, max_length=200, help_text="Keystone tenant id")    
265
266     #class Meta:
267     #    db_table = 'core_site_deployments'
268     #    #auto_created = Site
269