コード例 #1
0
ファイル: models.py プロジェクト: z147028571/freenas
class ConsulAlerts(Model):

    consulalert_type = models.CharField(
        verbose_name=_('Service Name'),
        max_length=20,
        choices=choices.CONSULALERTS_TYPES,
        default='AWS-SNS',
    )
    attributes = DictField(
        editable=False,
        verbose_name=_("Attributes"),
    )
    enabled = models.BooleanField(
        verbose_name=_("Enabled"),
        default=True,
    )

    class Meta:
        verbose_name = _("Alert Service")
        verbose_name_plural = _("Alert Services")
        ordering = ["consulalert_type"]

    class FreeAdmin:
        icon_model = "ConsulAlertsIcon"
        icon_object = "ConsulAlertsIcon"
        icon_add = "AddConsulAlertsIcon"
        icon_view = "ViewConsulAlertsIcon"

        exclude_fields = (
            'attributes',
            'id',
        )

    def __str__(self):
        return self.consulalert_type
コード例 #2
0
class AlertService(Model):
    name = models.CharField(
        max_length=120,
        verbose_name=_("Name"),
        help_text=_("Name to identify this alert service"),
    )
    type = models.CharField(
        verbose_name=_("Type"),
        max_length=20,
        default='Mail',
    )
    attributes = DictField(
        blank=True,
        editable=False,
        verbose_name=_("Attributes"),
    )
    enabled = models.BooleanField(
        verbose_name=_("Enabled"),
        default=True,
    )
    settings = DictField(
        blank=True,
        verbose_name=_("Settings"),
    )

    class Meta:
        verbose_name = _("Alert Service")
        verbose_name_plural = _("Alert Services")
        ordering = ["type"]

    class FreeAdmin:
        icon_model = "AlertServiceIcon"
        icon_object = "AlertServiceIcon"
        icon_add = "AddAlertServiceIcon"
        icon_view = "ViewAlertServiceIcon"

        exclude_fields = (
            'attributes',
            'settings',
            'id',
        )

    def __str__(self):
        return self.name
コード例 #3
0
ファイル: models.py プロジェクト: xj361685640/freenas
class Alert(Model):
    node = models.CharField(default='A', max_length=100)
    source = models.TextField()
    key = models.TextField()
    datetime = models.DateTimeField()
    level = models.IntegerField()
    title = models.TextField()
    args = DictField()
    dismissed = models.BooleanField()

    class Meta:
        unique_together = (('node', 'source', 'key'), )
コード例 #4
0
class AlertClasses(Model):
    classes = DictField(blank=True, )

    class Meta:
        verbose_name = _("Alerts")

    class FreeAdmin:
        deletable = False
        icon_model = "AlertServiceIcon"
        icon_object = "AlertServiceIcon"
        icon_view = "AlertServiceIcon"
        icon_add = "AlertServiceIcon"
コード例 #5
0
class Alert(Model):
    uuid = models.TextField()
    node = models.CharField(default='A', max_length=100)
    source = models.TextField()
    klass = models.TextField()
    args = DictField()
    key = models.TextField()
    datetime = models.DateTimeField()
    dismissed = models.BooleanField()
    text = models.TextField()

    class Meta:
        unique_together = (('node', 'klass', 'key'), )
コード例 #6
0
ファイル: models.py プロジェクト: zfstor/zfstor
class Device(Model):
    vm = models.ForeignKey(
        VM,
        verbose_name=_('VM'),
    )
    dtype = models.CharField(
        verbose_name=_('Type'),
        max_length=50,
        choices=choices.VM_DEVTYPES,
    )
    attributes = DictField(editable=False, )

    def __unicode__(self):
        return '{0}:{1}'.format(self.vm, self.get_dtype_display())
コード例 #7
0
ファイル: models.py プロジェクト: z147028571/freenas
class CloudCredentials(Model):
    name = models.CharField(
        verbose_name=_('Account Name'),
        max_length=100,
    )
    provider = models.CharField(
        verbose_name=_('Provider'),
        max_length=50,
        choices=choices.CLOUD_PROVIDERS,
    )
    attributes = DictField(editable=False, )

    def __str__(self):
        return self.name

    class Meta:
        verbose_name = _("Cloud Credential")
コード例 #8
0
ファイル: models.py プロジェクト: neszt/freenas
class CloudSync(Model):
    description = models.CharField(
        max_length=150,
        verbose_name=_('Description'),
    )
    path = PathField(
        verbose_name=_("Path"),
        abspath=False,
    )
    credential = models.ForeignKey(
        'system.CloudCredentials',
        verbose_name=_('Credential'),
    )
    attributes = DictField(editable=False, )
    minute = models.CharField(
        max_length=100,
        default="00",
        verbose_name=_("Minute"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-30 (as it is every Nth minute)."
                    "<br>Specific Minute: 0-59."),
    )
    hour = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Hour"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-12 (as it is every Nth hour)."
                    "<br>Specific Hour: 0-23."),
    )
    daymonth = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Day of month"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-15 (as its is every Nth day)."
                    "<br>Specific Day: 1-31."),
    )
    month = models.CharField(
        max_length=100,
        default='*',
        verbose_name=_("Month"),
    )
    dayweek = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Day of week"),
    )
    enabled = models.BooleanField(
        default=True,
        verbose_name=_("Enabled"),
        help_text=_(
            'Disabling will not stop any syncs which are in progress.'),
    )

    class Meta:
        verbose_name = _(u"Cloud Sync")
        verbose_name_plural = _(u"Cloud Syncs")
        ordering = ["description"]

    def __unicode__(self):
        return self.description

    def get_human_minute(self):
        if self.minute == '*':
            return _(u'Every minute')
        elif self.minute.startswith('*/'):
            return _(u'Every {0} minute(s)').format(self.minute.split('*/')[1])
        else:
            return self.minute

    def get_human_hour(self):
        if self.hour == '*':
            return _(u'Every hour')
        elif self.hour.startswith('*/'):
            return _(u'Every {0} hour(s)').format(self.hour.split('*/')[1])
        else:
            return self.hour

    def get_human_daymonth(self):
        if self.daymonth == '*':
            return _(u'Everyday')
        elif self.daymonth.startswith('*/'):
            return _(u'Every {0} days').format(self.daymonth.split('*/')[1])
        else:
            return self.daymonth

    def get_human_month(self):
        months = self.month.split(',')
        if len(months) == 12 or self.month == '*':
            return _("Every month")
        mchoices = dict(choices.MONTHS_CHOICES)
        labels = []
        for m in months:
            labels.append(unicode(mchoices[m]))
        return ', '.join(labels)

    def get_human_dayweek(self):
        weeks = self.dayweek.split(',')
        if len(weeks) == 7 or self.dayweek == '*':
            return _('Everyday')
        if weeks == map(str, xrange(1, 6)):
            return _('Weekdays')
        if weeks == map(str, xrange(6, 8)):
            return _('Weekends')
        wchoices = dict(choices.WEEKDAYS_CHOICES)
        labels = []
        for w in weeks:
            labels.append(unicode(wchoices[str(w)]))
        return ', '.join(labels)

    def run(self):
        with client as c:
            jid = c.call('backup.sync', self.id)
        return jid
コード例 #9
0
ファイル: models.py プロジェクト: sufideen/freenas
class bsdUsers(Model):

    USERNAME_FIELD = 'bsdusr_username'
    REQUIRED_FIELDS = []

    bsdusr_uid = models.IntegerField(
        verbose_name=_("User ID"),
        validators=[MinValueValidator(0), MaxValueValidator(4294967295)],
    )
    bsdusr_username = models.CharField(
        max_length=16,
        unique=True,
        default=_('User &'),
        verbose_name=_("Username")
    )
    bsdusr_unixhash = models.CharField(
        max_length=128,
        blank=True,
        default='*',
        verbose_name=_("Hashed UNIX password")
    )
    bsdusr_smbhash = models.CharField(
        max_length=128,
        blank=True,
        default='*',
        verbose_name=_("Hashed SMB password")
    )
    bsdusr_group = models.ForeignKey(
        bsdGroups,
        on_delete=models.SET(get_sentinel_group),
        verbose_name=_("Primary Group ID")
    )
    bsdusr_home = PathField(
        default="/nonexistent",
        verbose_name=_("Home Directory"),
        includes=["/root", "/nonexistent"],
    )
    bsdusr_shell = models.CharField(
        max_length=120,
        default='/bin/csh',
        verbose_name=_("Shell"),
        choices=choices.SHELL_CHOICES(),
    )
    bsdusr_full_name = models.CharField(
        max_length=120,
        verbose_name=_("Full Name")
    )
    bsdusr_builtin = models.BooleanField(
        default=False,
        editable=False,
        verbose_name=_("Built-in User"),
    )
    bsdusr_email = models.EmailField(
        verbose_name=_("E-mail"),
        blank=True
    )
    bsdusr_password_disabled = models.BooleanField(
        verbose_name=_("Disable password login"),
        default=False,
        help_text=_(
            'This disables all forms of password login, including for sharing.'
        ),
    )
    bsdusr_locked = models.BooleanField(
        verbose_name=_("Lock user"),
        default=False,
    )
    bsdusr_sudo = models.BooleanField(
        verbose_name=_("Permit Sudo"),
        default=False,
    )
    bsdusr_microsoft_account = models.BooleanField(
        verbose_name=_("Microsoft Account"),
        default=False
    )
    bsdusr_attributes = DictField(
        default=None,
        editable=False,
    )

    is_active = True
    is_staff = True
    objects = UserManager()

    @classmethod
    def has_root_password(cls):
        qs = cls.objects.filter(bsdusr_uid=0).exclude(bsdusr_unixhash='*')
        return qs.exists()

    @property
    def bsdusr_sshpubkey(self):
        keysfile = '%s/.ssh/authorized_keys' % self.bsdusr_home
        if not os.path.exists(keysfile):
            return ''
        try:
            with open(keysfile, 'r') as f:
                keys = f.read()
            return keys
        except:
            return ''

    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")
        ordering = ['bsdusr_builtin', 'bsdusr_username']

    def __str__(self):
        return self.bsdusr_username

    def get_username(self):
        "Return the identifying username for this User"
        return getattr(self, self.USERNAME_FIELD)

    def natural_key(self):
        return (self.get_username(),)

    @property
    def is_anonymous(self):
        """
        Always returns False. This is a way of comparing User objects to
        anonymous users.
        """
        return False

    @property
    def is_authenticated(self):
        """
        Always return True. This is a way to tell if the user has been
        authenticated in templates.
        """
        return True

    def set_password(self, password):
        # Django auth backend calls set_password even if user doesnt exist
        if not self.bsdusr_username or not self.id:
            time.sleep(0.1)
            return
        with client as c:
            pk = c.call('user.update', self.id, {'password': password})
        user = bsdUsers.objects.get(pk=pk)
        self.bsdusr_unixhash = user.bsdusr_unixhash
        self.bsdusr_smbhash = user.bsdusr_smbhash

    def check_password(self, raw_password):
        # Only allow uid 0 for now
        if self.bsdusr_uid != 0:
            return False
        if self.bsdusr_unixhash:
            if self.bsdusr_unixhash == 'x' or self.bsdusr_unixhash == '*':
                return False
            if isinstance(raw_password, bytes):
                raw_password = raw_password.decode('utf-8')
            return crypt.crypt(
                raw_password, str(self.bsdusr_unixhash)
            ) == str(self.bsdusr_unixhash)

    def save(self, *args, **kwargs):
        # TODO: Add last_login field
        if (
            'update_fields' in kwargs and
            'last_login' in kwargs['update_fields']
        ):
            kwargs['update_fields'].remove('last_login')
        super(bsdUsers, self).save(*args, **kwargs)
コード例 #10
0
ファイル: models.py プロジェクト: tejp/freenas
class CloudSync(Model):
    description = models.CharField(
        max_length=150,
        verbose_name=_('Description'),
    )
    direction = models.CharField(
        max_length=10,
        verbose_name=_("Direction"),
        help_text=_(
            "Push - From local to remote. Pull - From "
            "remote to local."
        ),
        default='PUSH',
        choices=(
            ('PUSH', _('Push')),
            ('PULL', _('Pull')),
        )
    )
    path = PathField(
        verbose_name=_("Path"),
        abspath=False,
    )
    credential = models.ForeignKey(
        'system.CloudCredentials',
        verbose_name=_('Credential'),
    )
    transfer_mode = models.CharField(
        verbose_name=_('Transfer Mode'),
        default='sync',
        choices=(
            ('SYNC', _('Sync')),
            ('COPY', _('Copy')),
            ('MOVE', _('Move')),
        ),
        max_length=20,
    )
    attributes = DictField(
        editable=False,
    )
    snapshot = models.BooleanField(
        verbose_name=_("Take snapshot"),
        help_text=_(
            "Take dataset snapshot before pushing data.",
        ),
    )
    pre_script = models.TextField(
        blank=True,
        verbose_name=_("Pre-script"),
        help_text=_(
            "Script to execute before running sync.",
        ),
    )
    post_script = models.TextField(
        blank=True,
        verbose_name=_("Post-script"),
        help_text=_(
            "Script to execute after running sync.",
        ),
    )
    encryption = models.BooleanField(
        verbose_name=_("Remote encryption"),
        help_text=_(
            "This option will push encrypted files and decrypt pulled files.",
        ),
    )
    filename_encryption = models.BooleanField(
        default=True,
        verbose_name=_("Filename encryption"),
        help_text=_(
            "Also encrypt filenames.",
        ),
    )
    encryption_password = models.CharField(
        blank=True,
        max_length=256,
        verbose_name=_("Encryption password"),
    )
    encryption_salt = models.CharField(
        blank=True,
        max_length=256,
        verbose_name=_("Encryption salt"),
    )
    args = models.TextField(
        blank=True,
        max_length=255,
        verbose_name=_("Auxiliary arguments"),
        help_text=_(
            "These arguments will be passed to rclone."
            "<br>See <a href=\"https://rclone.org/docs/\">https://rclone.org/docs/</a> for help"),
    )
    minute = models.CharField(
        max_length=100,
        default="00",
        verbose_name=_("Minute"),
        help_text=_(
            "Values allowed:"
            "<br>Slider: 0-30 (as it is every Nth minute)."
            "<br>Specific Minute: 0-59."),
    )
    hour = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Hour"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-12 (as it is every Nth hour)."
                    "<br>Specific Hour: 0-23."),
    )
    daymonth = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Day of month"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-15 (as its is every Nth day)."
                    "<br>Specific Day: 1-31."),
    )
    month = models.CharField(
        max_length=100,
        default='*',
        verbose_name=_("Month"),
    )
    dayweek = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Day of week"),
    )
    follow_symlinks = models.BooleanField(
        verbose_name=_("Follow symlinks"),
        help_text=_(
            "Follow symlinks and copy the pointed to item.",
        ),
    )
    transfers = models.IntegerField(
        null=True,
    )
    bwlimit = ListField(
        editable=False,
    )
    exclude = ListField(
        editable=False,
    )
    enabled = models.BooleanField(
        default=True,
        verbose_name=_("Enabled"),
        help_text=_(
            'Disabling will not stop any syncs which are in progress.'
        ),
    )

    class Meta:
        verbose_name = _("Cloud Sync")
        verbose_name_plural = _("Cloud Syncs")
        ordering = ["description"]

    def __str__(self):
        return self.description

    def run(self):
        with client as c:
            jid = c.call('cloudsync.sync', self.id)
        return jid
コード例 #11
0
class CloudSync(Model):
    description = models.CharField(
        max_length=150,
        verbose_name=_('Description'),
    )
    direction = models.CharField(
        max_length=10,
        verbose_name=_("Direction"),
        help_text=_("Push - From local to remote. Pull - From "
                    "remote to local."),
        default='PUSH',
        choices=(
            ('PUSH', _('Push')),
            ('PULL', _('Pull')),
        ))
    path = PathField(
        verbose_name=_("Path"),
        abspath=False,
    )
    credential = models.ForeignKey(
        'system.CloudCredentials',
        verbose_name=_('Credential'),
    )
    transfer_mode = models.CharField(
        verbose_name=_('Transfer Mode'),
        default='sync',
        choices=(
            ('SYNC', _('Sync')),
            ('COPY', _('Copy')),
            ('MOVE', _('Move')),
        ),
        max_length=20,
    )
    attributes = DictField(editable=False, )
    encryption = models.BooleanField(
        verbose_name=_("Remote encryption"),
        help_text=_(
            "This option will push encrypted files and decrypt pulled files.",
        ),
    )
    filename_encryption = models.BooleanField(
        default=True,
        verbose_name=_("Filename encryption"),
        help_text=_("Also encrypt filenames.", ),
    )
    encryption_password = models.CharField(
        blank=True,
        max_length=256,
        verbose_name=_("Encryption password"),
    )
    encryption_salt = models.CharField(
        blank=True,
        max_length=256,
        verbose_name=_("Encryption salt"),
    )
    minute = models.CharField(
        max_length=100,
        default="00",
        verbose_name=_("Minute"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-30 (as it is every Nth minute)."
                    "<br>Specific Minute: 0-59."),
    )
    hour = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Hour"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-12 (as it is every Nth hour)."
                    "<br>Specific Hour: 0-23."),
    )
    daymonth = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Day of month"),
        help_text=_("Values allowed:"
                    "<br>Slider: 0-15 (as its is every Nth day)."
                    "<br>Specific Day: 1-31."),
    )
    month = models.CharField(
        max_length=100,
        default='*',
        verbose_name=_("Month"),
    )
    dayweek = models.CharField(
        max_length=100,
        default="*",
        verbose_name=_("Day of week"),
    )
    enabled = models.BooleanField(
        default=True,
        verbose_name=_("Enabled"),
        help_text=_(
            'Disabling will not stop any syncs which are in progress.'),
    )

    class Meta:
        verbose_name = _("Cloud Sync")
        verbose_name_plural = _("Cloud Syncs")
        ordering = ["description"]

    def __str__(self):
        return self.description

    def get_human_minute(self):
        if self.minute == '*':
            return _('Every minute')
        elif self.minute.startswith('*/'):
            return _('Every {0} minute(s)').format(self.minute.split('*/')[1])
        else:
            return self.minute

    def get_human_hour(self):
        if self.hour == '*':
            return _('Every hour')
        elif self.hour.startswith('*/'):
            return _('Every {0} hour(s)').format(self.hour.split('*/')[1])
        else:
            return self.hour

    def get_human_daymonth(self):
        if self.daymonth == '*':
            return _('Everyday')
        elif self.daymonth.startswith('*/'):
            return _('Every {0} days').format(self.daymonth.split('*/')[1])
        else:
            return self.daymonth

    def get_human_month(self):
        months = self.month.split(',')
        if len(months) == 12 or self.month == '*':
            return _("Every month")
        mchoices = dict(choices.MONTHS_CHOICES)
        labels = []
        for m in months:
            labels.append(str(mchoices[m]))
        return ', '.join(labels)

    def get_human_dayweek(self):
        weeks = self.dayweek.split(',')
        if len(weeks) == 7 or self.dayweek == '*':
            return _('Everyday')
        if weeks == list(map(str, range(1, 6))):
            return _('Weekdays')
        if weeks == list(map(str, range(6, 8))):
            return _('Weekends')
        wchoices = dict(choices.WEEKDAYS_CHOICES)
        labels = []
        for w in weeks:
            labels.append(str(wchoices[str(w)]))
        return ', '.join(labels)

    def run(self):
        with client as c:
            jid = c.call('cloudsync.sync', self.id)
        return jid
コード例 #12
0
ファイル: models.py プロジェクト: smithlei/freenas
class bsdUsers(Model):

    USERNAME_FIELD = 'bsdusr_username'
    REQUIRED_FIELDS = []

    bsdusr_uid = models.IntegerField(
        verbose_name=_("User ID"),
        validators=[MinValueValidator(0),
                    MaxValueValidator(4294967295)],
    )
    bsdusr_username = models.CharField(max_length=16,
                                       unique=True,
                                       default=_('User &'),
                                       verbose_name=_("Username"))
    bsdusr_unixhash = models.CharField(max_length=128,
                                       blank=True,
                                       default='*',
                                       verbose_name=_("Hashed UNIX password"))
    bsdusr_smbhash = models.CharField(max_length=128,
                                      blank=True,
                                      default='*',
                                      verbose_name=_("Hashed SMB password"))
    bsdusr_group = models.ForeignKey(bsdGroups,
                                     on_delete=models.SET(get_sentinel_group),
                                     verbose_name=_("Primary Group ID"))
    bsdusr_home = PathField(
        default="/nonexistent",
        verbose_name=_("Home Directory"),
        includes=["/root", "/nonexistent"],
    )
    bsdusr_shell = models.CharField(
        max_length=120,
        default='/bin/csh',
        verbose_name=_("Shell"),
        choices=choices.SHELL_CHOICES(),
    )
    bsdusr_full_name = models.CharField(max_length=120,
                                        verbose_name=_("Full Name"))
    bsdusr_builtin = models.BooleanField(
        default=False,
        editable=False,
        verbose_name=_("Built-in User"),
    )
    bsdusr_email = models.EmailField(verbose_name=_("E-mail"), blank=True)
    bsdusr_password_disabled = models.BooleanField(
        verbose_name=_("Disable password login"),
        default=False,
        help_text=_(
            'This disables all forms of password login, including for sharing.'
        ),
    )
    bsdusr_locked = models.BooleanField(
        verbose_name=_("Lock user"),
        default=False,
    )
    bsdusr_sudo = models.BooleanField(
        verbose_name=_("Permit Sudo"),
        default=False,
    )
    bsdusr_microsoft_account = models.BooleanField(
        verbose_name=_("Microsoft Account"), default=False)
    bsdusr_attributes = DictField(
        default=None,
        editable=False,
    )

    is_active = True
    is_staff = True
    objects = UserManager()

    @classmethod
    def has_root_password(cls):
        qs = cls.objects.filter(bsdusr_uid=0).exclude(bsdusr_unixhash='*')
        return qs.exists()

    @property
    def bsdusr_sshpubkey(self):
        keysfile = '%s/.ssh/authorized_keys' % self.bsdusr_home
        if not os.path.exists(keysfile):
            return ''
        try:
            with open(keysfile, 'r') as f:
                keys = f.read()
            return keys
        except:
            return ''

    class Meta:
        verbose_name = _("User")
        verbose_name_plural = _("Users")
        ordering = ['bsdusr_builtin', 'bsdusr_username']

    def __str__(self):
        return self.bsdusr_username

    def get_username(self):
        "Return the identifying username for this User"
        return getattr(self, self.USERNAME_FIELD)

    def natural_key(self):
        return (self.get_username(), )

    @property
    def is_anonymous(self):
        """
        Always returns False. This is a way of comparing User objects to
        anonymous users.
        """
        return False

    @property
    def is_authenticated(self):
        """
        Always return True. This is a way to tell if the user has been
        authenticated in templates.
        """
        return True

    def set_password(self, password):
        # Django auth backend calls set_password even if user doesnt exist
        if not self.bsdusr_username or not self.id:
            time.sleep(0.1)
            return
        unixhash, smbhash = notifier().user_changepassword(
            username=self.bsdusr_username,
            password=password,
        )
        self.bsdusr_unixhash = unixhash
        self.bsdusr_smbhash = smbhash

    def check_password(self, raw_password):
        # Only allow uid 0 for now
        if self.bsdusr_uid != 0:
            return False
        if self.bsdusr_unixhash:
            if self.bsdusr_unixhash == 'x' or self.bsdusr_unixhash == '*':
                return False
            if isinstance(raw_password, bytes):
                raw_password = raw_password.decode('utf-8')
            return crypt.crypt(raw_password, str(self.bsdusr_unixhash)) == str(
                self.bsdusr_unixhash)

    def delete(self, using=None, reload=True, delete_group=True):
        from freenasUI.services.models import CIFS
        if self.bsdusr_builtin is True:
            raise ValueError(
                _("User %s is built-in and can not be deleted!") %
                (self.bsdusr_username))
        notifier().user_deleteuser(self.bsdusr_username)
        if domaincontroller_enabled():
            Samba4().user_delete(self.bsdusr_username)
        try:
            gobj = self.bsdusr_group
            count = bsdGroupMembership.objects.filter(
                bsdgrpmember_group=gobj).count()
            count2 = bsdUsers.objects.filter(bsdusr_group=gobj).exclude(
                id=self.id).count()
            if delete_group and not gobj.bsdgrp_builtin and count == 0 and count2 == 0:
                gobj.delete(reload=False, pwdelete=False)
        except:
            log.warn('Failed to delete primary group of %s',
                     self,
                     exc_info=True)
        cifs = CIFS.objects.latest('id')
        if cifs:
            if cifs.cifs_srv_guest == self.bsdusr_username:
                cifs.cifs_srv_guest = 'nobody'
                cifs.save()
        super(bsdUsers, self).delete(using)
        if reload:
            notifier().reload("user")

    def save(self, *args, **kwargs):
        # TODO: Add last_login field
        if ('update_fields' in kwargs
                and 'last_login' in kwargs['update_fields']):
            kwargs['update_fields'].remove('last_login')
        super(bsdUsers, self).save(*args, **kwargs)