class ReplRemote(Model): ssh_remote_hostname = models.CharField( max_length=120, verbose_name=_("Remote hostname"), ) ssh_remote_port = models.IntegerField( default=22, verbose_name=_("Remote port"), ) ssh_remote_dedicateduser_enabled = models.BooleanField( default=False, verbose_name=_("Remote Dedicated User Enabled"), ) ssh_remote_dedicateduser = UserField( verbose_name=_("Remote Dedicated User"), blank=True, null=True, default='', ) ssh_remote_hostkey = models.CharField( max_length=2048, verbose_name=_("Remote hostkey"), ) ssh_fast_cipher = models.BooleanField( default=False, verbose_name=_("High Speed Encryption Ciphers"), help_text=_( "Enabling this may increase transfer speed on high " "speed/low latency local networks. It uses less secure " "encryption algorithms than the defaults, which make it less " "desirable on untrusted networks.") ) class Meta: verbose_name = _(u"Remote Replication Host") verbose_name_plural = _(u"Remote Replication Hosts") def delete(self): rv = super(ReplRemote, self).delete() notifier().reload("ssh") return rv def __unicode__(self): return self.ssh_remote_hostname
class ReplRemote(Model): ssh_remote_hostname = models.CharField( max_length=120, verbose_name=_("Remote hostname"), ) ssh_remote_port = models.IntegerField( default=22, verbose_name=_("Remote port"), ) ssh_remote_dedicateduser_enabled = models.BooleanField( default=False, verbose_name=_("Remote Dedicated User Enabled"), ) ssh_remote_dedicateduser = UserField( verbose_name=_("Remote Dedicated User"), blank=True, null=True, default='', ) ssh_remote_hostkey = models.CharField( max_length=2048, verbose_name=_("Remote hostkey"), ) ssh_cipher = models.CharField( max_length=20, verbose_name=_('Encryption Cipher'), choices=choices.REPL_CIPHER, default='standard', ) class Meta: verbose_name = _(u"Remote Replication Host") verbose_name_plural = _(u"Remote Replication Hosts") def delete(self): rv = super(ReplRemote, self).delete() notifier().reload("ssh") return rv def __unicode__(self): return u"%s:%s" % (self.ssh_remote_hostname, self.ssh_remote_port)
class NFS_Share(Model): nfs_comment = models.CharField( max_length=120, verbose_name=_("Comment"), blank=True, ) nfs_network = models.TextField( verbose_name=_("Authorized networks"), help_text=_( "Networks that are authorized to access the NFS share." " Specify network numbers of the form 1.2.3.4/xx where xx is " "the number of bits of netmask."), blank=True, ) nfs_hosts = models.TextField( verbose_name=_("Authorized IP addresses or hosts"), help_text=_("IP addresses or hostnames that are authorized to " "access the NFS share."), blank=True, ) nfs_alldirs = models.BooleanField( verbose_name=_("All Directories"), help_text= _("Allow mounting of any subdirectory under this mount point if selected. Otherwise, only the top level directory can be mounted." ), ) nfs_ro = models.BooleanField( verbose_name=_("Read Only"), help_text=_("Export the share read only. Writes are not permitted.")) nfs_quiet = models.BooleanField( verbose_name=_("Quiet"), help_text= _("Inhibit syslog warnings if there are problems with exporting this share." )) nfs_maproot_user = UserField( verbose_name=_("Maproot User"), max_length=120, blank=True, null=True, default='', help_text=_("If a user is selected, the root user is limited to " "that user's permissions")) nfs_maproot_group = GroupField( verbose_name=_("Maproot Group"), max_length=120, blank=True, null=True, default='', help_text=_("If a group is selected, the root user will also be " "limited to that group's permissions")) nfs_mapall_user = UserField( verbose_name=_("Mapall User"), max_length=120, blank=True, null=True, default='', help_text=_("The specified user's permissions are used by all " "clients")) nfs_mapall_group = GroupField( verbose_name=_("Mapall Group"), max_length=120, blank=True, null=True, default='', help_text=_("The specified group's permission are used by all " "clients")) def __unicode__(self): if self.nfs_comment: return unicode(self.nfs_comment) return u"[%s]" % ', '.join([p.path for p in self.paths.all()]) def delete(self, *args, **kwargs): super(NFS_Share, self).delete(*args, **kwargs) notifier().reload("nfs") @property def nfs_paths(self): return u"%s" % ', '.join([p.path for p in self.paths.all()]) class Meta: verbose_name = _("Unix (NFS) Share") verbose_name_plural = _("Unix (NFS) Shares")
class Advanced(Model): adv_consolemenu = models.BooleanField( verbose_name=_("Show Text Console without Password Prompt"), default=False, ) adv_serialconsole = models.BooleanField( verbose_name=_("Use Serial Console"), default=False, ) adv_serialport = models.CharField( max_length=120, default="0x2f8", help_text=_( "Set this to match your serial port address (0x3f8, 0x2f8, etc.)"), verbose_name=_("Serial Port Address"), choices=choices.SERIAL_CHOICES(), ) adv_serialspeed = models.CharField( max_length=120, choices=choices.SERIAL_SPEED, default="9600", help_text=_("Set this to match your serial port speed"), verbose_name=_("Serial Port Speed")) adv_consolescreensaver = models.BooleanField( verbose_name=_("Enable screen saver"), default=False, ) adv_powerdaemon = models.BooleanField( verbose_name=_("Enable powerd (Power Saving Daemon)"), default=False, ) adv_swapondrive = models.IntegerField( validators=[MinValueValidator(0)], verbose_name=_( "Swap size on each drive in GiB, affects new disks " "only. Setting this to 0 disables swap creation completely " "(STRONGLY DISCOURAGED)."), default=2, ) adv_consolemsg = models.BooleanField( verbose_name=_("Show console messages in the footer"), default=True, ) adv_traceback = models.BooleanField( verbose_name=_("Show tracebacks in case of fatal errors"), default=True, ) adv_advancedmode = models.BooleanField( verbose_name=_("Show advanced fields by default"), default=False, help_text=_( "By default only essential fields are shown. Fields considered " "advanced can be displayed through the Advanced Mode button."), ) adv_autotune = models.BooleanField( verbose_name=_("Enable autotune"), default=False, help_text=_( "Attempt to automatically tune the network and ZFS system control " "variables based on memory available."), ) adv_debugkernel = models.BooleanField( verbose_name=_("Enable debug kernel"), default=False, help_text=_( "The kernel built with debug symbols will be booted instead."), ) adv_uploadcrash = models.BooleanField( verbose_name=_( "Enable automatic upload of kernel crash dumps and daily telemetry" ), default=True, ) adv_anonstats = models.BooleanField( verbose_name=_("Enable report anonymous statistics"), default=True, editable=False, ) adv_anonstats_token = models.TextField( blank=True, editable=False, ) adv_motd = models.TextField( max_length=1024, verbose_name=_("MOTD banner"), default='Welcome', blank=True, ) adv_boot_scrub = models.IntegerField( default=7, editable=False, ) adv_periodic_notifyuser = UserField( default="root", verbose_name=_("Periodic Notification User"), help_text= _("If you wish periodic emails to be sent to a different email address than " "the alert emails are set to (root) set an email address for a user and " "select that user in the dropdown.")) adv_cpu_in_percentage = models.BooleanField( default=False, verbose_name=_("Report CPU usage in percentage"), help_text=_( "collectd will report CPU usage in percentage instead of \"jiffies\" " "if this is checked."), ) adv_graphite = models.CharField( max_length=120, default="", blank=True, verbose_name=_("Remote Graphite Server Hostname"), help_text=_( "A hostname or IP here will be used as the destination to send collectd " "data to using the graphite plugin to collectd.")) adv_fqdn_syslog = models.BooleanField( verbose_name=_("Use FQDN for logging"), default=False, ) adv_sed_user = models.CharField( max_length=120, choices=choices.SED_USER, default="user", help_text=_("User passed to camcontrol security -u " "for unlocking SEDs"), verbose_name=_("camcontrol security user")) class Meta: verbose_name = _("Advanced") class FreeAdmin: deletable = False
class Rsync(Model): rsync_path = PathField( verbose_name=_("Path"), abspath=False, ) rsync_remotehost = models.CharField( max_length=120, verbose_name=_("Remote Host"), help_text=_("IP Address or hostname. " "Specify user@hostname or user@ip-address " "if your remote machine user and above rsync " "task user are different."), ) rsync_remoteport = models.SmallIntegerField( default=22, verbose_name=_("Remote SSH Port"), help_text=_("SSH Port"), validators=[MinValueValidator(1), MaxValueValidator(65535)], ) rsync_mode = models.CharField( max_length=20, choices=choices.RSYNC_MODE_CHOICES, default='module', ) rsync_remotemodule = models.CharField( max_length=120, verbose_name=_("Remote Module Name"), blank=True, help_text=_("Name of the module defined in the remote rsync daemon"), ) rsync_remotepath = models.CharField( max_length=255, verbose_name=_("Remote Path"), blank=True, help_text=_("Path on remote host to rsync to, e.g. /mnt/tank"), ) rsync_direction = models.CharField( max_length=10, verbose_name=_("Direction"), help_text=_("Push - From local to remote machine. Pull - From " "remote to local machine."), default='push', choices=choices.RSYNC_DIRECTION, ) rsync_desc = models.CharField( max_length=120, verbose_name=_("Short description"), blank=True, ) rsync_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."), ) rsync_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."), ) rsync_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."), ) rsync_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) rsync_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) rsync_user = UserField( max_length=60, verbose_name=_("User"), help_text=_("The user to run the command"), ) rsync_recursive = models.BooleanField( verbose_name=_("Recursive"), help_text=_("Recurse into directories"), default=True, ) rsync_times = models.BooleanField( verbose_name=_("Times"), help_text=_("Preserve modification times"), default=True, ) rsync_compress = models.BooleanField( verbose_name=_("Compress"), help_text=_("Compress data during the transfer"), default=True, ) rsync_archive = models.BooleanField( verbose_name=_("Archive"), help_text=_("Archive mode"), default=False, ) rsync_delete = models.BooleanField( verbose_name=_("Delete"), help_text=_( "Delete files on the receiving side that don't exist on sender"), default=False, ) rsync_quiet = models.BooleanField( verbose_name=_("Quiet"), help_text=_("Suppress non-error messages"), default=False, ) rsync_preserveperm = models.BooleanField( verbose_name=_("Preserve permissions"), help_text=_("This option causes the receiving rsync to set the " "destination permissions to be the same as the source " "permissions"), default=False, ) rsync_preserveattr = models.BooleanField( verbose_name=_("Preserve extended attributes"), help_text=_("This option causes rsync to update the remote " "extended attributes to be the same as the local ones"), default=False, ) rsync_delayupdates = models.BooleanField( verbose_name=_("Delay Updates"), help_text=_("Put all updated files into place at the end"), default=True, ) rsync_extra = models.TextField( verbose_name=_("Extra options"), help_text=_("Extra options to rsync command line (usually empty)"), blank=True) rsync_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Rsync Task") verbose_name_plural = _("Rsync Tasks") ordering = ["rsync_path", "rsync_desc"] def __unicode__(self): if self.rsync_desc: return self.rsync_desc elif self.rsync_mode == 'module': return self.rsync_remotemodule else: return self.rsync_remotepath def get_human_minute(self): if self.rsync_minute == '*': return _(u'Every minute') elif self.rsync_minute.startswith('*/'): return _(u'Every {0} minute(s)').format( self.rsync_minute.split('*/')[1]) else: return self.rsync_minute def get_human_hour(self): if self.rsync_hour == '*': return _(u'Every hour') elif self.rsync_hour.startswith('*/'): return _(u'Every {0} hour(s)').format( self.rsync_hour.split('*/')[1]) else: return self.rsync_hour def get_human_daymonth(self): if self.rsync_daymonth == '*': return _(u'Everyday') elif self.rsync_daymonth.startswith('*/'): return _(u'Every {0} days').format( self.rsync_daymonth.split('*/')[1]) else: return self.rsync_daymonth def get_human_month(self): months = self.rsync_month.split(',') if len(months) == 12 or self.rsync_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.rsync_dayweek.split(',') if len(weeks) == 7 or self.rsync_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 commandline(self): line = '/usr/bin/lockf -s -t 0 -k "%s" /usr/local/bin/rsync' % ( self.rsync_path) if self.rsync_recursive: line += ' -r' if self.rsync_times: line += ' -t' if self.rsync_compress: line += ' -z' if self.rsync_archive: line += ' -a' if self.rsync_preserveperm: line += ' -p' if self.rsync_preserveattr: line += ' -X' if self.rsync_delete: line += ' --delete-delay' if self.rsync_delayupdates: line += ' --delay-updates' if self.rsync_extra: line += ' %s' % self.rsync_extra # Do not use username if one is specified in host field # See #5096 for more details if '@' in self.rsync_remotehost: remote = self.rsync_remotehost else: remote = '"%s"@%s' % ( self.rsync_user, self.rsync_remotehost, ) if self.rsync_mode == 'module': if self.rsync_direction == 'push': line += ' "%s" %s::"%s"' % ( self.rsync_path, remote, self.rsync_remotemodule, ) else: line += ' %s::"%s" "%s"' % ( remote, self.rsync_remotemodule, self.rsync_path, ) else: line += (' -e "ssh -p %d -o BatchMode=yes ' '-o StrictHostKeyChecking=yes"') % (self.rsync_remoteport) if self.rsync_direction == 'push': line += ' "%s" %s:\\""%s"\\"' % ( self.rsync_path, remote, self.rsync_remotepath, ) else: line += ' %s:\\""%s"\\" "%s"' % ( remote, self.rsync_remotepath, self.rsync_path, ) if self.rsync_quiet: line += ' > /dev/null 2>&1' return line def run(self): proc = subprocess.Popen([ "/usr/local/bin/python2", "/usr/local/www/freenasUI/tools/runnow.py", "-t", "rsync", "-i", str(self.id), ]) proc.communicate() def delete(self): super(Rsync, self).delete() try: notifier().restart("cron") except: pass
class CronJob(Model): cron_user = UserField(max_length=60, verbose_name=_("User"), help_text=_("The user to run the command")) cron_command = models.TextField(verbose_name=_("Command"), ) cron_description = models.CharField( max_length=200, verbose_name=_("Short description"), blank=True, ) cron_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) cron_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) cron_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) cron_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) cron_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) cron_stdout = models.BooleanField( default=True, verbose_name=_("Redirect Stdout"), help_text=_("Redirect the standard output to /dev/null. In other " "words, disable output."), ) cron_stderr = models.BooleanField( default=False, verbose_name=_("Redirect Stderr"), help_text=_("Redirect the standard error output to /dev/null. In " "other words, disable error output."), ) cron_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Cron Job") verbose_name_plural = _("Cron Jobs") ordering = ["cron_description", "cron_user"] def __unicode__(self): if self.cron_description: return self.cron_description return u"%d (%s)" % (self.id, self.cron_user) def get_human_minute(self): if self.cron_minute == '*': return _(u'Every minute') elif self.cron_minute.startswith('*/'): return _(u'Every {0} minute(s)').format( self.cron_minute.split('*/')[1]) else: return self.cron_minute def get_human_hour(self): if self.cron_hour == '*': return _(u'Every hour') elif self.cron_hour.startswith('*/'): return _(u'Every {0} hour(s)').format( self.cron_hour.split('*/')[1]) else: return self.cron_hour def get_human_daymonth(self): if self.cron_daymonth == '*': return _(u'Everyday') elif self.cron_daymonth.startswith('*/'): return _(u'Every {0} days').format( self.cron_daymonth.split('*/')[1]) else: return self.cron_daymonth def get_human_month(self): months = self.cron_month.split(",") if len(months) == 12 or self.cron_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): # TODO: # 1. Carve out the days input so that way one can say: # Mon-Fri + Saturday -> Weekdays + Saturday. # 2. Get rid of the duplicate code. weeks = self.cron_dayweek.split(',') if len(weeks) == 7 or self.cron_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 commandline(self): line = self.cron_command if self.cron_stdout: line += ' > /dev/null' if self.cron_stderr: line += ' 2> /dev/null' else: line += ' 2>&1' return line def run(self): proc = subprocess.Popen([ "/usr/local/bin/python2", "/usr/local/www/freenasUI/tools/runnow.py", "-t", "cronjob", "-i", str(self.id), ]) proc.communicate() def delete(self): super(CronJob, self).delete() try: notifier().restart("cron") except: pass
class NFS_Share(Model): nfs_comment = models.CharField( max_length=120, verbose_name=_("Comment"), blank=True, ) nfs_network = models.TextField( verbose_name=_("Authorized networks"), help_text=_( "Networks that are authorized to access the NFS share." " Specify network numbers of the form 1.2.3.4/xx where xx is " "the number of bits of netmask."), blank=True, ) nfs_hosts = models.TextField( verbose_name=_("Authorized IP addresses or hosts"), help_text=_("IP addresses or hostnames that are authorized to " "access the NFS share."), blank=True, ) nfs_alldirs = models.BooleanField( verbose_name=_('All Directories'), help_text=_( 'Allow mounting of any subdirectory under this mount point if' 'selected. Otherwise, only the top level directory can be mounted.' ), default=False, ) nfs_ro = models.BooleanField( verbose_name=_('Read Only'), help_text=_('Export the share read only. Writes are not permitted.'), default=False, ) nfs_quiet = models.BooleanField( verbose_name=_('Quiet'), help_text=_( 'Inhibit syslog warnings if there are problems with exporting ' 'this share.'), default=False, ) nfs_maproot_user = UserField( verbose_name=_("Maproot User"), max_length=120, blank=True, null=True, default='', help_text=_( "The credentials of the specified user is used for remote access " "by root."), ) nfs_maproot_group = GroupField( verbose_name=_("Maproot Group"), max_length=120, blank=True, null=True, default='', help_text=_( "The credentials of the specified group is used for remote access " "by root."), ) nfs_mapall_user = UserField( verbose_name=_("Mapall User"), max_length=120, blank=True, null=True, default='', help_text=_( "The credentials of the specified user is used for remote access " "by all users."), ) nfs_mapall_group = GroupField( verbose_name=_("Mapall Group"), max_length=120, blank=True, null=True, default='', help_text=_( "The credentials of the specified group is used for remote access " "by all users."), ) nfs_security = MultiSelectField( verbose_name=_('Security'), max_length=200, blank=True, choices=( ('sys', 'sys'), ('krb5', 'krb5'), ('krb5i', 'krb5i'), ('krb5p', 'krb5p'), ), ) def __str__(self): if self.nfs_comment: return str(self.nfs_comment) return "[%s]" % ', '.join([p.path for p in self.paths.all()]) def delete(self, *args, **kwargs): super(NFS_Share, self).delete(*args, **kwargs) notifier().reload("nfs") @property def nfs_paths(self): return [p.path for p in self.paths.all()] class Meta: verbose_name = _("Unix (NFS) Share") verbose_name_plural = _("Unix (NFS) Shares")
class Advanced(Model): adv_consolemenu = models.BooleanField( verbose_name=_("Show Text Console without Password Prompt"), default=False, ) adv_serialconsole = models.BooleanField( verbose_name=_("Use Serial Console"), default=False, ) adv_serialport = models.CharField( max_length=120, default="0x2f8", help_text=_( "Set this to match your serial port address (0x3f8, 0x2f8, etc.)"), verbose_name=_("Serial Port Address")) adv_serialspeed = models.CharField( max_length=120, choices=choices.SERIAL_SPEED, default="9600", help_text=_("Set this to match your serial port speed"), verbose_name=_("Serial Port Speed")) adv_powerdaemon = models.BooleanField( verbose_name=_("Enable powerd (Power Saving Daemon)"), default=False, ) adv_swapondrive = models.IntegerField( validators=[MinValueValidator(0)], verbose_name=_( "Swap size on each drive in GiB, affects new disks " "only. Setting this to 0 disables swap creation completely " "(STRONGLY DISCOURAGED)."), default=2, ) adv_consolemsg = models.BooleanField( verbose_name=_("Show console messages in the footer"), default=True, ) adv_traceback = models.BooleanField( verbose_name=_("Show tracebacks in case of fatal errors"), default=True, ) adv_advancedmode = models.BooleanField( verbose_name=_("Show advanced fields by default"), default=False, help_text=_( "By default only essential fields are shown. Fields considered " "advanced can be displayed through the Advanced Mode button."), ) adv_autotune = models.BooleanField( verbose_name=_("Enable autotune"), default=False, help_text=_( "Attempt to automatically tune the network and ZFS system control " "variables based on memory available."), ) adv_debugkernel = models.BooleanField( verbose_name=_("Enable debug kernel"), default=False, help_text=_( "The kernel built with debug symbols will be booted instead."), ) adv_uploadcrash = models.BooleanField( verbose_name=_( "Enable automatic upload of kernel crash dumps and daily telemetry" ), default=True, ) adv_anonstats = models.BooleanField( verbose_name=_("Enable report anonymous statistics"), default=True, editable=False, ) adv_anonstats_token = models.TextField( blank=True, editable=False, ) adv_motd = models.TextField( max_length=10240, verbose_name=_("MOTD banner"), default='Welcome', blank=True, ) adv_boot_scrub = models.IntegerField(default=7, ) adv_periodic_notifyuser = UserField( default="root", verbose_name=_("Periodic Notification User"), help_text= _("If you wish periodic emails to be sent to a different email address than " "the alert emails are set to (root) set an email address for a user and " "select that user in the dropdown.")) adv_fqdn_syslog = models.BooleanField( verbose_name=_("Use FQDN for logging"), default=False, ) adv_sed_user = models.CharField( max_length=120, choices=choices.SED_USER, default="user", help_text=_("User passed to camcontrol security -u " "for unlocking SEDs"), verbose_name=_("ATA Security User")) adv_sed_passwd = models.CharField( max_length=120, blank=True, help_text=_("Global password to unlock SED disks."), verbose_name=_("SED Password"), ) class Meta: verbose_name = _("Advanced") class FreeAdmin: deletable = False def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.adv_sed_passwd: try: self.adv_sed_passwd = notifier().pwenc_decrypt( self.adv_sed_passwd) except Exception: log.debug('Failed to decrypt SED password', exc_info=True) self.adv_sed_passwd = '' self._adv_sed_passwd_encrypted = False def save(self, *args, **kwargs): if self.adv_sed_passwd and not self._adv_sed_passwd_encrypted: self.adv_sed_passwd = notifier().pwenc_encrypt(self.adv_sed_passwd) self._adv_sed_passwd_encrypted = True return super().save(*args, **kwargs)
class Rsync(Model): rsync_path = PathField( verbose_name=_("Path"), abspath=False, ) rsync_remotehost = models.CharField( max_length=120, verbose_name=_("Remote Host"), help_text=_("IP Address or hostname"), ) rsync_remoteport = models.SmallIntegerField( default=22, verbose_name=_("Remote SSH Port"), help_text=_("SSH Port"), validators=[MinValueValidator(1), MaxValueValidator(65535)], ) rsync_mode = models.CharField( max_length=20, choices=choices.RSYNC_MODE_CHOICES, default='module', ) rsync_remotemodule = models.CharField( max_length=120, verbose_name=_("Remote Module Name"), blank=True, help_text=_("Name of the module defined in the remote rsync " "daemon"), ) rsync_remotepath = models.CharField( max_length=120, verbose_name=_("Remote Path"), blank=True, help_text=_("Path on remote host to rsync to, e.g. /mnt/tank"), ) rsync_direction = models.CharField( max_length=10, verbose_name=_("Direction"), help_text=_("Push - From local to remote machine. Pull - From " "remote to local machine."), default='push', choices=choices.RSYNC_DIRECTION, ) rsync_desc = models.CharField( max_length=120, verbose_name=_("Short description"), blank=True, ) rsync_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) rsync_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) rsync_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) rsync_month = models.CharField( max_length=100, default='1,2,3,4,5,6,7,8,9,a,b,c', verbose_name=_("Month"), ) rsync_dayweek = models.CharField( max_length=100, default="1,2,3,4,5,6,7", verbose_name=_("Day of week"), ) rsync_user = UserField( max_length=60, verbose_name=_("User"), help_text=_("The user to run the command"), ) rsync_recursive = models.BooleanField( verbose_name=_("Recursive"), help_text=_("Recurse into directories"), default=True, ) rsync_times = models.BooleanField( verbose_name=_("Times"), help_text=_("Preserve modification times"), default=True, ) rsync_compress = models.BooleanField( verbose_name=_("Compress"), help_text=_("Compress data during the transfer"), default=True, ) rsync_archive = models.BooleanField( verbose_name=_("Archive"), help_text=_("Archive mode"), default=False, ) rsync_delete = models.BooleanField( verbose_name=_("Delete"), help_text=_("Delete files on the receiving side that don't exist " "on sender"), default=False, ) rsync_quiet = models.BooleanField( verbose_name=_("Quiet"), help_text=_("Suppress non-error messages"), default=False, ) rsync_preserveperm = models.BooleanField( verbose_name=_("Preserve permissions"), help_text=_("This option causes the receiving rsync to set the " "destination permissions to be the same as the source " "permissions"), default=False, ) rsync_preserveattr = models.BooleanField( verbose_name=_("Preserve extended attributes"), help_text=_("This option causes rsync to update the remote " "extended attributes to be the same as the local ones"), default=False, ) rsync_extra = models.TextField( verbose_name=_("Extra options"), help_text=_("Extra options to rsync command line (usually empty)"), blank=True) rsync_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Rsync Task") verbose_name_plural = _("Rsync Tasks") ordering = ["rsync_path", "rsync_desc"] def __unicode__(self): if self.rsync_desc: return self.rsync_desc elif self.rsync_mode == 'module': return self.rsync_remotemodule else: return self.rsync_remotepath def get_human_minute(self): if self.rsync_minute == '*': return _(u'Every minute') elif self.rsync_minute.startswith('*/'): return _(u'Every %s minute(s)') % self.rsync_minute.split('*/')[1] else: return self.rsync_minute def get_human_hour(self): if self.rsync_hour == '*': return _(u'Every hour') elif self.rsync_hour.startswith('*/'): return _(u'Every %s hour(s)') % self.rsync_hour.split('*/')[1] else: return self.rsync_hour def get_human_daymonth(self): if self.rsync_daymonth == '*': return _(u'Everyday') elif self.rsync_daymonth.startswith('*/'): return _(u'Every %s days') % self.rsync_daymonth.split('*/')[1] else: return self.rsync_daymonth def get_human_month(self): months = self.rsync_month.split(',') if len(months) == 12 or self.rsync_month == '*': return _("Every month") mchoices = dict(choices.MONTHS_CHOICES) labels = [] for m in months: if m in ('10', '11', '12'): m = chr(87 + int(m)) labels.append(unicode(mchoices[m])) return ', '.join(labels) def get_human_dayweek(self): weeks = self.rsync_dayweek.split(',') if len(weeks) == 7 or self.rsync_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 delete(self): super(Rsync, self).delete() try: notifier().restart("cron") except: pass
class CronJob(Model): cron_user = UserField(max_length=60, verbose_name=_("User"), help_text=_("The user to run the command")) cron_command = models.TextField(verbose_name=_("Command"), ) cron_description = models.CharField( max_length=200, verbose_name=_("Short description"), blank=True, ) cron_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) cron_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) cron_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) cron_month = models.CharField( max_length=100, default='1,2,3,4,5,6,7,8,9,a,b,c', verbose_name=_("Month"), ) cron_dayweek = models.CharField( max_length=100, default="1,2,3,4,5,6,7", verbose_name=_("Day of week"), ) cron_stdout = models.BooleanField( default=True, verbose_name=_("Redirect Stdout"), help_text=_("Redirect the standard output to /dev/null. In other " "words, disable output."), ) cron_stderr = models.BooleanField( default=False, verbose_name=_("Redirect Stderr"), help_text=_("Redirect the standard error output to /dev/null. In " "other words, disable error output."), ) cron_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Cron Job") verbose_name_plural = _("Cron Jobs") ordering = ["cron_description", "cron_user"] def __unicode__(self): if self.cron_description: return self.cron_description return u"%d (%s)" % (self.id, self.cron_user) def get_human_minute(self): if self.cron_minute == '*': return _(u'Every minute') elif self.cron_minute.startswith('*/'): return _(u'Every %s minute(s)') % self.cron_minute.split('*/')[1] else: return self.cron_minute def get_human_hour(self): if self.cron_hour == '*': return _(u'Every hour') elif self.cron_hour.startswith('*/'): return _(u'Every %s hour(s)') % self.cron_hour.split('*/')[1] else: return self.cron_hour def get_human_daymonth(self): if self.cron_daymonth == '*': return _(u'Everyday') elif self.cron_daymonth.startswith('*/'): return _(u'Every %s days') % self.cron_daymonth.split('*/')[1] else: return self.cron_daymonth def get_human_month(self): months = self.cron_month.split(",") if len(months) == 12 or self.cron_month == '*': return _("Every month") mchoices = dict(choices.MONTHS_CHOICES) labels = [] for m in months: if m in ('10', '11', '12'): m = chr(87 + int(m)) labels.append(unicode(mchoices[m])) return ', '.join(labels) def get_human_dayweek(self): # TODO: # 1. Carve out the days input so that way one can say: # Mon-Fri + Saturday -> Weekdays + Saturday. # 2. Get rid of the duplicate code. weeks = self.cron_dayweek.split(',') if len(weeks) == 7 or self.cron_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 delete(self): super(CronJob, self).delete() try: notifier().restart("cron") except: pass
class Rsync(Model): rsync_path = PathField( verbose_name=_("Path"), abspath=False, ) rsync_remotehost = models.CharField( max_length=120, verbose_name=_("Remote Host"), help_text=_("IP Address or hostname. " "Specify user@hostname or user@ip-address " "if your remote machine user and above rsync " "task user are different." ), ) rsync_remoteport = models.SmallIntegerField( default=22, verbose_name=_("Remote SSH Port"), help_text=_("SSH Port"), validators=[MinValueValidator(1), MaxValueValidator(65535)], ) rsync_mode = models.CharField( max_length=20, choices=choices.RSYNC_MODE_CHOICES, default='module', ) rsync_remotemodule = models.CharField( max_length=120, verbose_name=_("Remote Module Name"), blank=True, help_text=_("Name of the module defined in the remote rsync daemon"), ) rsync_remotepath = models.CharField( max_length=255, verbose_name=_("Remote Path"), blank=True, help_text=_("Path on remote host to rsync to, e.g. /mnt/tank"), ) rsync_direction = models.CharField( max_length=10, verbose_name=_("Direction"), help_text=_( "Push - From local to remote machine. Pull - From " "remote to local machine." ), default='push', choices=choices.RSYNC_DIRECTION, ) rsync_desc = models.CharField( max_length=120, verbose_name=_("Short description"), blank=True, ) rsync_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."), ) rsync_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."), ) rsync_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."), ) rsync_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) rsync_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) rsync_user = UserField( max_length=60, verbose_name=_("User"), help_text=_("The user to run the command"), ) rsync_recursive = models.BooleanField( verbose_name=_("Recursive"), help_text=_("Recurse into directories"), default=True, ) rsync_times = models.BooleanField( verbose_name=_("Times"), help_text=_("Preserve modification times"), default=True, ) rsync_compress = models.BooleanField( verbose_name=_("Compress"), help_text=_("Compress data during the transfer"), default=True, ) rsync_archive = models.BooleanField( verbose_name=_("Archive"), help_text=_("Archive mode"), default=False, ) rsync_delete = models.BooleanField( verbose_name=_("Delete"), help_text=_( "Delete files on the receiving side that don't exist on sender" ), default=False, ) rsync_quiet = models.BooleanField( verbose_name=_("Quiet"), help_text=_("Suppress non-error messages"), default=False, ) rsync_preserveperm = models.BooleanField( verbose_name=_("Preserve permissions"), help_text=_( "This option causes the receiving rsync to set the " "destination permissions to be the same as the source " "permissions" ), default=False, ) rsync_preserveattr = models.BooleanField( verbose_name=_("Preserve extended attributes"), help_text=_( "This option causes rsync to update the remote " "extended attributes to be the same as the local ones" ), default=False, ) rsync_delayupdates = models.BooleanField( verbose_name=_("Delay Updates"), help_text=_("Put all updated files into place at the end"), default=True, ) rsync_extra = models.TextField( verbose_name=_("Extra options"), help_text=_("Extra options to rsync command line (usually empty)"), blank=True ) rsync_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Rsync Task") verbose_name_plural = _("Rsync Tasks") ordering = ["rsync_path", "rsync_desc"] def __str__(self): if self.rsync_desc: return self.rsync_desc elif self.rsync_mode == 'module': return self.rsync_remotemodule else: return self.rsync_remotepath
class CronJob(Model): cron_user = UserField( max_length=60, verbose_name=_("User"), help_text=_("The user to run the command") ) cron_command = models.TextField( verbose_name=_("Command"), ) cron_description = models.CharField( max_length=200, verbose_name=_("Short description"), blank=True, ) cron_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) cron_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) cron_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) cron_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) cron_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) cron_stdout = models.BooleanField( default=True, verbose_name=_("Redirect Stdout"), help_text=_( "Redirect the standard output to /dev/null. In other " "words, disable output." ), ) cron_stderr = models.BooleanField( default=False, verbose_name=_("Redirect Stderr"), help_text=_( "Redirect the standard error output to /dev/null. In " "other words, disable error output." ), ) cron_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Cron Job") verbose_name_plural = _("Cron Jobs") ordering = ["cron_description", "cron_user"] def __str__(self): if self.cron_description: return self.cron_description return "%d (%s)" % (self.id, self.cron_user)
class CronJob(Model): cron_user = UserField(max_length=60, verbose_name=_("User"), help_text=_("The user to run the command")) cron_command = models.TextField(verbose_name=_("Command"), ) cron_description = models.CharField( max_length=200, verbose_name=_("Short description"), blank=True, ) cron_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) cron_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) cron_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) cron_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) cron_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) cron_stdout = models.BooleanField( default=True, verbose_name=_("Redirect Stdout"), help_text=_("Redirect the standard output to /dev/null. In other " "words, disable output."), ) cron_stderr = models.BooleanField( default=False, verbose_name=_("Redirect Stderr"), help_text=_("Redirect the standard error output to /dev/null. In " "other words, disable error output."), ) cron_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Cron Job") verbose_name_plural = _("Cron Jobs") ordering = ["cron_description", "cron_user"] def __unicode__(self): if self.cron_description: return self.cron_description return u"%d (%s)" % (self.id, self.cron_user) def get_human_minute(self): if self.cron_minute == '*': return _(u'Every minute') elif self.cron_minute.startswith('*/'): return _(u'Every {0} minute(s)').format( self.cron_minute.split('*/')[1]) else: return self.cron_minute def get_human_hour(self): if self.cron_hour == '*': return _(u'Every hour') elif self.cron_hour.startswith('*/'): return _(u'Every {0} hour(s)').format( self.cron_hour.split('*/')[1]) else: return self.cron_hour def get_human_daymonth(self): if self.cron_daymonth == '*': return _(u'Everyday') elif self.cron_daymonth.startswith('*/'): return _(u'Every {0} days').format( self.cron_daymonth.split('*/')[1]) else: return self.cron_daymonth def get_human_month(self): months = self.cron_month.split(",") if len(months) == 12 or self.cron_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): # TODO: # 1. Carve out the days input so that way one can say: # Mon-Fri + Saturday -> Weekdays + Saturday. # 2. Get rid of the duplicate code. weeks = self.cron_dayweek.split(',') if len(weeks) == 7 or self.cron_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 commandline(self): line = self.cron_command if self.cron_stdout: line += ' > /dev/null' if self.cron_stderr: line += ' 2> /dev/null' else: line += ' 2>&1' return line def run(self): if os.fork() == 0: for i in xrange(1, 1024): try: os.close(i) except OSError: pass try: passwd = pwd.getpwnam(self.cron_user.encode('utf8')) os.umask(0) os.setgid(passwd.pw_gid) os.setuid(passwd.pw_uid) try: os.chdir(passwd.pw_dir) except: pass proc = subprocess.Popen( '%s | logger -t cron' % self.commandline(), shell=True, env={ 'PATH': ('/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:' '/usr/local/sbin:/root/bin'), }, ) except Exception, e: log.debug("Failed to run cron") log_traceback(log=log) os._exit(0)
class Advanced(Model): adv_consolemenu = models.BooleanField( verbose_name=_("Enable Console Menu"), default=False, ) adv_serialconsole = models.BooleanField( verbose_name=_("Use Serial Console"), default=False, ) adv_serialport = models.CharField( max_length=120, default="0x2f8", help_text=_( "Set this to match your serial port address (0x3f8, 0x2f8, etc.)"), verbose_name=_("Serial Port Address"), choices=choices.SERIAL_CHOICES(), ) adv_serialspeed = models.CharField( max_length=120, choices=choices.SERIAL_SPEED, default="9600", help_text=_("Set this to match your serial port speed"), verbose_name=_("Serial Port Speed")) adv_consolescreensaver = models.BooleanField( verbose_name=_("Enable screen saver"), default=False, ) adv_powerdaemon = models.BooleanField( verbose_name=_("Enable powerd (Power Saving Daemon)"), default=False, ) adv_swapondrive = models.IntegerField( validators=[MinValueValidator(0)], verbose_name=_( "Swap size on each drive in GiB, affects new disks " "only. Setting this to 0 disables swap creation completely " "(STRONGLY DISCOURAGED)."), default=2) adv_consolemsg = models.BooleanField( verbose_name=_("Show console messages in the footer"), default=True) adv_traceback = models.BooleanField( verbose_name=_("Show tracebacks in case of fatal errors"), default=True) adv_advancedmode = models.BooleanField( verbose_name=_("Show advanced fields by default"), default=False) adv_autotune = models.BooleanField(verbose_name=_("Enable autotune"), default=False) adv_debugkernel = models.BooleanField( verbose_name=_("Enable debug kernel"), default=False) adv_uploadcrash = models.BooleanField( verbose_name=_( "Enable automatic upload of kernel crash dumps and daily telemetry" ), default=True, ) adv_anonstats = models.BooleanField( verbose_name=_("Enable report anonymous statistics"), default=True, editable=False) adv_anonstats_token = models.TextField(blank=True, editable=False) # TODO: need geom_eli in kernel #adv_encswap = models.BooleanField( # verbose_name = _("Encrypt swap space"), # default=False) adv_motd = models.TextField( max_length=1024, verbose_name=_("MOTD banner"), default='Welcome', ) adv_boot_scrub = models.IntegerField( default=35, editable=False, ) adv_periodic_notifyuser = UserField( default="root", verbose_name=_("Periodic Notification User"), help_text= _("If you wish periodic emails to be sent to a different email address than " "the alert emails are set to (root) set an email address for a user and " "select that user in the dropdown.")) class Meta: verbose_name = _("Advanced") class FreeAdmin: deletable = False
class CronJob(Model): cron_user = UserField(max_length=60, verbose_name=_("User"), help_text=_("The user to run the command")) cron_command = models.TextField(verbose_name=_("Command"), ) cron_description = models.CharField( max_length=200, verbose_name=_("Short description"), blank=True, ) cron_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) cron_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) cron_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) cron_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) cron_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) cron_stdout = models.BooleanField( default=True, verbose_name=_("Redirect Stdout"), help_text=_("Redirect the standard output to /dev/null. In other " "words, disable output."), ) cron_stderr = models.BooleanField( default=False, verbose_name=_("Redirect Stderr"), help_text=_("Redirect the standard error output to /dev/null. In " "other words, disable error output."), ) cron_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Cron Job") verbose_name_plural = _("Cron Jobs") ordering = ["cron_description", "cron_user"] def __str__(self): if self.cron_description: return self.cron_description return "%d (%s)" % (self.id, self.cron_user) def commandline(self): line = self.cron_command if self.cron_stdout: line += ' > /dev/null' if self.cron_stderr: line += ' 2> /dev/null' else: line += ' 2>&1' return line def run(self): proc = subprocess.Popen([ "/usr/local/www/freenasUI/tools/runnow.py", "-t", "cronjob", "-i", str(self.id), ]) proc.communicate()
class Rsync(Model): rsync_path = PathField( verbose_name=_("Path"), abspath=False, ) rsync_remotehost = models.CharField( max_length=120, verbose_name=_("Remote Host"), help_text=_("IP Address or hostname"), ) rsync_remoteport = models.SmallIntegerField( default=22, verbose_name=_("Remote SSH Port"), help_text=_("SSH Port"), validators=[MinValueValidator(1), MaxValueValidator(65535)], ) rsync_mode = models.CharField( max_length=20, choices=choices.RSYNC_MODE_CHOICES, default='module', ) rsync_remotemodule = models.CharField( max_length=120, verbose_name=_("Remote Module Name"), blank=True, help_text=_("Name of the module defined in the remote rsync " "daemon"), ) rsync_remotepath = models.CharField( max_length=120, verbose_name=_("Remote Path"), blank=True, help_text=_("Path on remote host to rsync to, e.g. /mnt/tank"), ) rsync_direction = models.CharField( max_length=10, verbose_name=_("Direction"), help_text=_("Push - From local to remote machine. Pull - From " "remote to local machine."), default='push', choices=choices.RSYNC_DIRECTION, ) rsync_desc = models.CharField( max_length=120, verbose_name=_("Short description"), blank=True, ) rsync_minute = models.CharField( max_length=100, default="00", verbose_name=_("Minute"), help_text=_("Values 0-59 allowed."), ) rsync_hour = models.CharField( max_length=100, default="*", verbose_name=_("Hour"), help_text=_("Values 0-23 allowed."), ) rsync_daymonth = models.CharField( max_length=100, default="*", verbose_name=_("Day of month"), help_text=_("Values 1-31 allowed."), ) rsync_month = models.CharField( max_length=100, default='*', verbose_name=_("Month"), ) rsync_dayweek = models.CharField( max_length=100, default="*", verbose_name=_("Day of week"), ) rsync_user = UserField( max_length=60, verbose_name=_("User"), help_text=_("The user to run the command"), ) rsync_recursive = models.BooleanField( verbose_name=_("Recursive"), help_text=_("Recurse into directories"), default=True, ) rsync_times = models.BooleanField( verbose_name=_("Times"), help_text=_("Preserve modification times"), default=True, ) rsync_compress = models.BooleanField( verbose_name=_("Compress"), help_text=_("Compress data during the transfer"), default=True, ) rsync_archive = models.BooleanField( verbose_name=_("Archive"), help_text=_("Archive mode"), default=False, ) rsync_delete = models.BooleanField( verbose_name=_("Delete"), help_text=_("Delete files on the receiving side that don't exist " "on sender"), default=False, ) rsync_quiet = models.BooleanField( verbose_name=_("Quiet"), help_text=_("Suppress non-error messages"), default=False, ) rsync_preserveperm = models.BooleanField( verbose_name=_("Preserve permissions"), help_text=_("This option causes the receiving rsync to set the " "destination permissions to be the same as the source " "permissions"), default=False, ) rsync_preserveattr = models.BooleanField( verbose_name=_("Preserve extended attributes"), help_text=_("This option causes rsync to update the remote " "extended attributes to be the same as the local ones"), default=False, ) rsync_extra = models.TextField( verbose_name=_("Extra options"), help_text=_("Extra options to rsync command line (usually empty)"), blank=True) rsync_enabled = models.BooleanField( default=True, verbose_name=_("Enabled"), ) class Meta: verbose_name = _("Rsync Task") verbose_name_plural = _("Rsync Tasks") ordering = ["rsync_path", "rsync_desc"] def __unicode__(self): if self.rsync_desc: return self.rsync_desc elif self.rsync_mode == 'module': return self.rsync_remotemodule else: return self.rsync_remotepath def get_human_minute(self): if self.rsync_minute == '*': return _(u'Every minute') elif self.rsync_minute.startswith('*/'): return _(u'Every %s minute(s)') % self.rsync_minute.split('*/')[1] else: return self.rsync_minute def get_human_hour(self): if self.rsync_hour == '*': return _(u'Every hour') elif self.rsync_hour.startswith('*/'): return _(u'Every %s hour(s)') % self.rsync_hour.split('*/')[1] else: return self.rsync_hour def get_human_daymonth(self): if self.rsync_daymonth == '*': return _(u'Everyday') elif self.rsync_daymonth.startswith('*/'): return _(u'Every %s days') % self.rsync_daymonth.split('*/')[1] else: return self.rsync_daymonth def get_human_month(self): months = self.rsync_month.split(',') if len(months) == 12 or self.rsync_month == '*': return _("Every month") mchoices = dict(choices.MONTHS_CHOICES) labels = [] for m in months: if m in ('10', '11', '12'): m = chr(87 + int(m)) labels.append(unicode(mchoices[m])) return ', '.join(labels) def get_human_dayweek(self): weeks = self.rsync_dayweek.split(',') if len(weeks) == 7 or self.rsync_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 commandline(self): line = '/usr/bin/lockf -s -t 0 -k \'%s\' /usr/local/bin/rsync' % ( self.rsync_path) if self.rsync_recursive: line += ' -r' if self.rsync_times: line += ' -t' if self.rsync_compress: line += ' -z' if self.rsync_archive: line += ' -a' if self.rsync_preserveperm: line += ' -p' if self.rsync_preserveattr: line += ' -X' if self.rsync_delete: line += ' --delete-delay' line += ' --delay-updates %s' % self.rsync_extra # Do not use username if one is specified in host field # See #5096 for more details if '@' in self.rsync_remotehost: remote = self.rsync_remotehost else: remote = '%s@%s' % ( self.rsync_user, self.rsync_remotehost, ) if self.rsync_mode == 'module': if self.rsync_direction == 'push': line += ' \'%s\' %s::%s' % ( self.rsync_path, remote, self.rsync_remotemodule, ) else: line += ' %s::%s \'%s\'' % ( remote, self.rsync_remotemodule, self.rsync_path, ) else: line += (' -e \'ssh -p %d -o BatchMode=yes ' '-o StrictHostKeyChecking=yes\'') % ( self.rsync_remoteport) if self.rsync_direction == 'push': line += ' \'%s\' %s:\'%s\'' % ( self.rsync_path, remote, self.rsync_remotepath, ) else: line += ' %s:\'%s\' \'%s\'' % ( remote, self.rsync_remotepath, self.rsync_path, ) if self.rsync_quiet: line += ' > /dev/null 2>&1' return line def run(self): subprocess.Popen( 'su -m %s -c "%s" 2>&1 | logger -t rsync' % ( self.rsync_user, self.commandline(), ), shell=True, ) def delete(self): super(Rsync, self).delete() try: notifier().restart("cron") except: pass