Beispiel #1
0
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)
Beispiel #2
0
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)
Beispiel #3
0
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"
Beispiel #4
0
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"