class HpcService(Service): class Meta: app_label = "hpc" verbose_name = "HPC Service" cmi_hostname = StrippedCharField(max_length=254, null=True, blank=True) hpc_port80 = models.BooleanField(default=True, help_text="Enable port 80 for HPC") watcher_hpc_network = StrippedCharField(max_length=254, null=True, blank=True, help_text="Network for hpc_watcher to contact hpc instance") watcher_dnsdemux_network = StrippedCharField(max_length=254, null=True, blank=True, help_text="Network for hpc_watcher to contact dnsdemux instance") watcher_dnsredir_network = StrippedCharField(max_length=254, null=True, blank=True, help_text="Network for hpc_watcher to contact dnsredir instance") @property def scale(self): hpc_slices = [x for x in self.slices.all() if "hpc" in x.name] if not hpc_slices: return 0 return hpc_slices[0].instances.count() @scale.setter def scale(self, value): self.set_scale = value def save(self, *args, **kwargs): super(HpcService, self).save(*args, **kwargs) # scale up/down scale = getattr(self, "set_scale", None) if scale is not None: exclude_slices = [x for x in self.slices.all() if "cmi" in x.name] self.adjust_scale(slice_hint="hpc", scale=scale, exclusive_slices = exclude_slices, max_per_node=1)
class HpcHealthCheck(XOSBase): class Meta: app_label = "hpc" KIND_CHOICES = (('dns', 'DNS'), ('http', 'HTTP'), ('nameserver', 'Name Server')) hpcService = models.ForeignKey(HpcService, blank = True, null=True) kind = models.CharField(max_length=30, choices=KIND_CHOICES, default="dns") resource_name = StrippedCharField(max_length=1024, blank=False, null=False) result_contains = StrippedCharField(max_length=1024, blank=True, null=True) result_min_size = models.IntegerField(null=True, blank=True) result_max_size = models.IntegerField(null=True, blank=True) def __unicode__(self): return self.resource_name @classmethod def filter_by_hpcService(cls, qs, hpcService): # This should be overridden by descendant classes that want to perform # filtering of visible objects by user. return qs.filter(hpcService=hpcService)
class User(AbstractBaseUser, PlModelMixIn): plural_name = "Users" @property def remote_password(self): return hashlib.md5(self.password).hexdigest()[:12] class Meta: app_label = "core" email = models.EmailField( verbose_name='email address', max_length=255, unique=True, db_index=True, ) username = StrippedCharField(max_length=255, default="Something") firstname = StrippedCharField(help_text="person's given name", max_length=200) lastname = StrippedCharField(help_text="person's surname", max_length=200) phone = StrippedCharField(null=True, blank=True, help_text="phone number contact", max_length=100) user_url = models.URLField(null=True, blank=True) site = models.ForeignKey('Site', related_name='users', help_text="Site this user will be homed too") public_key = models.TextField(null=True, blank=True, max_length=1024, help_text="Public key string") is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=True) is_readonly = models.BooleanField(default=False) is_registering = models.BooleanField(default=False) is_appuser = models.BooleanField(default=False) login_page = StrippedCharField( help_text="send this user to a specific page on login", max_length=200, null=True, blank=True) created = models.DateTimeField(auto_now_add=True) updated = models.DateTimeField(auto_now=True) enacted = models.DateTimeField(null=True, default=None) policed = models.DateTimeField(null=True, default=None) backend_status = StrippedCharField(max_length=1024, default="Provisioning in progress") backend_need_delete = models.BooleanField(default=False) backend_need_reap = models.BooleanField(default=False) deleted = models.BooleanField(default=False) write_protect = models.BooleanField(default=False) lazy_blocked = models.BooleanField(default=False) no_sync = models.BooleanField(default=False) # prevent object sync no_policy = models.BooleanField(default=False) # prevent model_policy run timezone = TimeZoneField() dashboards = models.ManyToManyField('DashboardView', through='UserDashboardView', blank=True) policy_status = models.CharField(default="0 - Policy in process", max_length=1024, null=True) objects = UserManager() deleted_objects = DeletedUserManager() USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['firstname', 'lastname'] PI_FORBIDDEN_FIELDS = ["is_admin", "site", "is_staff"] USER_FORBIDDEN_FIELDS = [ "is_admin", "is_active", "site", "is_staff", "is_readonly" ] def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) self._initial = self._dict # for PlModelMixIn self.silent = False def isReadOnlyUser(self): return self.is_readonly def get_full_name(self): # The user is identified by their email address return self.email def get_short_name(self): # The user is identified by their email address return self.email @property def keyname(self): return self.email[:self.email.find('@')] def __unicode__(self): return self.email def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def is_superuser(self): return False def get_dashboards(self): DEFAULT_DASHBOARDS = ["Tenant"] dashboards = sorted(list(self.userdashboardviews.all()), key=attrgetter('order')) dashboards = [x.dashboardView for x in dashboards] if (not dashboards) and (not self.is_appuser): for dashboardName in DEFAULT_DASHBOARDS: dbv = dashboardview.DashboardView.objects.filter( name=dashboardName) if dbv: dashboards.append(dbv[0]) return dashboards # def get_roles(self): # from core.models.site import SitePrivilege # from core.models.slice import SliceMembership # # site_privileges = SitePrivilege.objects.filter(user=self) # slice_memberships = SliceMembership.objects.filter(user=self) # roles = defaultdict(list) # for site_privilege in site_privileges: # roles[site_privilege.role.role_type].append(site_privilege.site.login_base) # for slice_membership in slice_memberships: # roles[slice_membership.role.role_type].append(slice_membership.slice.name) # return roles def delete(self, *args, **kwds): # so we have something to give the observer purge = kwds.get('purge', False) if purge: del kwds['purge'] silent = kwds.get('silent', False) if silent: del kwds['silent'] try: purge = purge or observer_disabled except NameError: pass if (purge): super(User, self).delete(*args, **kwds) else: if (not self.write_protect): self.deleted = True self.enacted = None self.policed = None self.save(update_fields=['enacted', 'deleted', 'policed'], silent=silent) collector = XOSCollector( using=router.db_for_write(self.__class__, instance=self)) collector.collect([self]) with transaction.atomic(): for (k, models) in collector.data.items(): for model in models: if model.deleted: # in case it's already been deleted, don't delete again continue model.deleted = True model.enacted = None model.policed = None model.save(update_fields=[ 'enacted', 'deleted', 'policed' ], silent=silent) def save(self, *args, **kwargs): if not self.id: self.set_password(self.password) if self.is_active and self.is_registering: self.send_temporary_password() self.is_registering = False # let the user specify silence as either a kwarg or an instance varible silent = self.silent if "silent" in kwargs: silent = silent or kwargs.pop("silent") caller_kind = "unknown" if ('synchronizer' in threading.current_thread().name): caller_kind = "synchronizer" if "caller_kind" in kwargs: caller_kind = kwargs.pop("caller_kind") always_update_timestamp = False if "always_update_timestamp" in kwargs: always_update_timestamp = always_update_timestamp or kwargs.pop( "always_update_timestamp") # SMBAKER: if an object is trying to delete itself, or if the observer # is updating an object's backend_* fields, then let it slip past the # composite key check. ignore_composite_key_check = False if "update_fields" in kwargs: ignore_composite_key_check = True for field in kwargs["update_fields"]: if not (field in [ "backend_register", "backend_status", "deleted", "enacted", "updated" ]): ignore_composite_key_check = False if (caller_kind != "synchronizer") or always_update_timestamp: self.updated = timezone.now() self.username = self.email super(User, self).save(*args, **kwargs) self.push_redis_event() self._initial = self._dict def send_temporary_password(self): password = User.objects.make_random_password() self.set_password(password) subject, from_email, to = 'OpenCloud Account Credentials', '*****@*****.**', str( self.email) text_content = 'This is an important message.' userUrl = "http://%s/" % get_request().get_host() html_content = """<p>Your account has been created on OpenCloud. Please log in <a href=""" + userUrl + """>here</a> to activate your account<br><br>Username: """ + \ self.email + """<br>Temporary Password: """ + password + \ """<br>Please change your password once you successully login into the site.</p>""" msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() def apply_profile(self, profile): if profile == "regular": self.is_appuser = False self.is_admin = False elif profile == "cp": self.is_appuser = True self.is_admin = False for db in self.userdashboardviews.all(): db.delete() def get_content_type_key(self): ct = ContentType.objects.get_for_model(self.__class__) return "%s.%s" % (ct.app_label, ct.model) @staticmethod def get_content_type_from_key(key): (app_name, model_name) = key.split(".") return ContentType.objects.get_by_natural_key(app_name, model_name) @staticmethod def get_content_object(content_type, object_id): ct = User.get_content_type_from_key(content_type) cls = ct.model_class() return cls.objects.get(id=object_id) ''' This function is hardcoded here because we do not yet generate the User class''' def can_access(self, ctx): return security.user_policy_security_check(self, ctx), "user_policy"
class User(AbstractBaseUser, PlModelMixIn): plural_name = "Users" @property def remote_password(self): return hashlib.md5(self.password).hexdigest()[:12] class Meta: app_label = "core" email = models.EmailField( verbose_name="email address", max_length=255, unique=True, db_index=True ) username = StrippedCharField(max_length=255, default="Something") firstname = StrippedCharField(help_text="person's given name", max_length=200) lastname = StrippedCharField(help_text="person's surname", max_length=200) phone = StrippedCharField( null=True, blank=True, help_text="phone number contact", max_length=100 ) user_url = models.URLField(null=True, blank=True) site = models.ForeignKey( "Site", related_name="users", help_text="Site this user will be homed too" ) public_key = models.TextField( null=True, blank=True, max_length=1024, help_text="Public key string" ) is_active = models.BooleanField(default=True) is_admin = models.BooleanField(default=False) is_staff = models.BooleanField(default=True) is_readonly = models.BooleanField(default=False) is_registering = models.BooleanField(default=False) is_appuser = models.BooleanField(default=False) login_page = StrippedCharField( help_text="send this user to a specific page on login", max_length=200, null=True, blank=True, ) created = models.DateTimeField( help_text="Time this model was created", auto_now_add=True, null=False, blank=False, ) updated = models.DateTimeField( help_text="Time this model was changed by a non-synchronizer", default=now, null=False, blank=False, ) enacted = models.DateTimeField( default=None, help_text="When synced, set to the timestamp of the data that was synced", null=True, blank=True, ) policed = models.DateTimeField( default=None, help_text="When policed, set to the timestamp of the data that was policed", null=True, blank=True, ) backend_status = StrippedCharField( max_length=1024, default="Provisioning in progress" ) backend_code = models.IntegerField(default=0, null=False) backend_need_delete = models.BooleanField(default=False) backend_need_reap = models.BooleanField(default=False) deleted = models.BooleanField(default=False) write_protect = models.BooleanField(default=False) lazy_blocked = models.BooleanField(default=False) no_sync = models.BooleanField(default=False) # prevent object sync no_policy = models.BooleanField(default=False) # prevent model_policy run timezone = models.CharField( max_length=100, null=True, blank=True, default=settings.TIME_ZONE ) leaf_model_name = models.CharField( help_text="The most specialized model in this chain of inheritance, often defined by a service developer", max_length=1024, null=False, ) policy_status = models.CharField( default="0 - Policy in process", max_length=1024, null=True ) policy_code = models.IntegerField(default=0, null=True) backend_need_delete_policy = models.BooleanField( help_text="True if delete model_policy must be run before object can be reaped", default=False, null=False, blank=True, ) xos_managed = models.BooleanField( help_text="True if xos is responsible for creating/deleting this object", default=True, null=False, blank=True, ) backend_handle = models.CharField( help_text="Handle used by the backend to track this object", max_length=1024, null=True, blank=True, ) changed_by_step = models.DateTimeField( default=None, help_text="Time this model was changed by a sync step", null=True, blank=True, ) changed_by_policy = models.DateTimeField( default=None, help_text="Time this model was changed by a model policy", null=True, blank=True, ) objects = UserManager() deleted_objects = DeletedUserManager() USERNAME_FIELD = "email" REQUIRED_FIELDS = ["firstname", "lastname"] PI_FORBIDDEN_FIELDS = ["is_admin", "site", "is_staff"] USER_FORBIDDEN_FIELDS = ["is_admin", "is_active", "site", "is_staff", "is_readonly"] def __init__(self, *args, **kwargs): super(User, self).__init__(*args, **kwargs) self._initial = self._dict # for PlModelMixIn self.silent = False def isReadOnlyUser(self): return self.is_readonly def get_full_name(self): # The user is identified by their email address return self.email def get_short_name(self): # The user is identified by their email address return self.email @property def keyname(self): return self.email[: self.email.find("@")] def __unicode__(self): return self.email def has_perm(self, perm, obj=None): "Does the user have a specific permission?" # Simplest possible answer: Yes, always return True def has_module_perms(self, app_label): "Does the user have permissions to view the app `app_label`?" # Simplest possible answer: Yes, always return True def is_superuser(self): return False def delete(self, *args, **kwds): # so we have something to give the observer purge = kwds.get("purge", False) if purge: del kwds["purge"] silent = kwds.get("silent", False) if silent: del kwds["silent"] try: purge = purge or observer_disabled except NameError: pass if purge: super(User, self).delete(*args, **kwds) else: if not self.write_protect: self.deleted = True self.enacted = None self.policed = None self.save( update_fields=["enacted", "deleted", "policed"], silent=silent ) collector = XOSCollector( using=router.db_for_write(self.__class__, instance=self) ) collector.collect([self]) with transaction.atomic(): for (k, models) in collector.data.items(): for model in models: if model.deleted: # in case it's already been deleted, don't delete again continue model.deleted = True model.enacted = None model.policed = None model.save( update_fields=["enacted", "deleted", "policed"], silent=silent, ) def has_important_changes(self): """ Determine whether the model has changes that should be reflected in one of the changed_by_* timestamps. Ignores various feedback and bookkeeping state set by synchronizers. """ for field_name in self.changed_fields: if field_name in [ "policed", "updated", "enacted", "changed_by_step", "changed_by_policy", ]: continue if field_name.startswith("backend_"): continue if field_name.startswith("policy_"): continue return True return False def save(self, *args, **kwargs): if not self.leaf_model_name: self.leaf_model_name = "User" if not self.id: self.set_password(self.password) if self.is_active and self.is_registering: self.send_temporary_password() self.is_registering = False # let the user specify silence as either a kwarg or an instance varible silent = self.silent if "silent" in kwargs: silent = silent or kwargs.pop("silent") caller_kind = "unknown" if "caller_kind" in kwargs: caller_kind = kwargs.pop("caller_kind") update_fields = None if "update_fields" in kwargs: # NOTE(smbaker): modifying update_fields will cause kwargs["update_fields"] to be modified. This is # intended, as kwargs will be passed to save() below. update_fields = kwargs["update_fields"] # NOTE(smbaker): always_update_timestamp still has some relevance for event_steps and pull_steps that # want to cause an update. For model_policies or sync_steps it should no longer be required. always_update_timestamp = False if "always_update_timestamp" in kwargs: always_update_timestamp = always_update_timestamp or kwargs.pop( "always_update_timestamp" ) is_sync_save = False if "is_sync_save" in kwargs: is_sync_save = kwargs.pop("is_sync_save") is_policy_save = False if "is_policy_save" in kwargs: is_policy_save = kwargs.pop("is_policy_save") if (caller_kind != "synchronizer") or always_update_timestamp: self.updated = timezone.now() else: # We're not auto-setting timestamp, but let's check to make sure that the caller hasn't tried to set our # timestamp backward... if (self.updated != self._initial["updated"]) and ( (not update_fields) or ("updated" in update_fields) ): log.info( "Synchronizer tried to change `updated` timestamp on model %s from %s to %s. Ignored." % (self, self._initial["updated"], self.updated) ) self.updated = self._initial["updated"] if is_sync_save and self.has_important_changes(): self.changed_by_step = timezone.now() if update_fields: update_fields.append("changed_by_step") if is_policy_save and self.has_important_changes(): self.changed_by_policy = timezone.now() if update_fields: update_fields.append("changed_by_policy") if not self.username: self.username = self.email if not self.deleted: self.full_clean() super(User, self).save(*args, **kwargs) self.push_messagebus_event() self._initial = self._dict def send_temporary_password(self): password = User.objects.make_random_password() self.set_password(password) subject, from_email, to = ( "OpenCloud Account Credentials", "*****@*****.**", str(self.email), ) text_content = "This is an important message." userUrl = "http://%s/" % get_request().get_host() html_content = ( """<p>Your account has been created on OpenCloud. Please log in <a href=""" + userUrl + """>here</a> to activate your account<br><br>Username: """ + self.email + """<br>Temporary Password: """ + password + """<br>Please change your password once you successully login into the site.</p>""" ) msg = EmailMultiAlternatives(subject, text_content, from_email, [to]) msg.attach_alternative(html_content, "text/html") msg.send() def apply_profile(self, profile): if profile == "regular": self.is_appuser = False self.is_admin = False elif profile == "cp": self.is_appuser = True self.is_admin = False def get_content_type_key(self): ct = ContentType.objects.get_for_model(self.__class__) return "%s.%s" % (ct.app_label, ct.model) @staticmethod def get_content_type_from_key(key): (app_name, model_name) = key.split(".") return ContentType.objects.get_by_natural_key(app_name, model_name) @staticmethod def get_content_object(content_type, object_id): ct = User.get_content_type_from_key(content_type) cls = ct.model_class() return cls.objects.get(id=object_id) """ This function is hardcoded here because we do not yet generate the User class""" def can_access(self, ctx): return security.user_policy_security_check(self, ctx), "user_policy"