def _show_schedule_setup_notification(): """Show a notification hinting to setup a remote backup schedule.""" from plinth.notification import Notification message = gettext_noop( 'Enable an automatic backup schedule for data safety. Prefer an ' 'encrypted remote backup location or an extra attached disk.') data = { 'app_name': 'translate:' + gettext_noop('Backups'), 'app_icon': 'fa-files-o' } title = gettext_noop('Enable a Backup Schedule') actions_ = [{ 'type': 'link', 'class': 'primary', 'text': gettext_noop('Go to {app_name}'), 'url': 'backups:index' }, { 'type': 'dismiss' }] Notification.update_or_create(id='backups-remote-schedule', app_id='backups', severity='info', title=title, message=message, actions=actions_, data=data, group='admin')
def _warn_about_low_ram_space(request): """Warn about insufficient RAM space.""" from plinth.notification import Notification memory_info = _get_memory_info() if memory_info['free_bytes'] < 1024**3: # Translators: This is the unit of computer storage Mebibyte similar to # Megabyte. memory_available_unit = gettext_noop('MiB') memory_available = memory_info['free_bytes'] / 1024**2 else: # Translators: This is the unit of computer storage Gibibyte similar to # Gigabyte. memory_available_unit = gettext_noop('GiB') memory_available = memory_info['free_bytes'] / 1024**3 show = False if memory_info['percent_used'] > 90: severity = 'error' advice_message = gettext_noop( 'You should disable some apps to reduce memory usage.') show = True elif memory_info['percent_used'] > 75: severity = 'warning' advice_message = gettext_noop( 'You should not install any new apps on this system.') show = True if not show: try: Notification.get('diagnostics-low-ram-space').delete() except KeyError: pass return message = gettext_noop( # xgettext:no-python-format 'System is low on memory: {percent_used}% used, {memory_available} ' '{memory_available_unit} free. {advice_message}') title = gettext_noop('Low Memory') data = { 'app_icon': 'fa-heartbeat', 'app_name': 'translate:' + gettext_noop('Diagnostics'), 'percent_used': f'{memory_info["percent_used"]:.1f}', 'memory_available': f'{memory_available:.1f}', 'memory_available_unit': 'translate:' + memory_available_unit, 'advice_message': 'translate:' + advice_message } actions = [{'type': 'dismiss'}] Notification.update_or_create(id='diagnostics-low-ram-space', app_id='diagnostics', severity=severity, title=title, message=message, actions=actions, data=data, group='admin')
def warn_about_low_disk_space(request): """Warn about insufficient space on root partition.""" from plinth.notification import Notification try: root_info = get_disk_info('/') except PlinthError as exception: logger.exception('Error getting information about root partition: %s', exception) return show = False if root_info['percent_used'] > 90 or root_info['free_gib'] < 1: severity = 'error' show = True elif root_info['percent_used'] > 75 or root_info['free_gib'] < 2: severity = 'warning' show = True if not show: try: Notification.get('storage-low-disk-space').delete() except KeyError: pass else: message = ugettext_noop( # xgettext:no-python-format 'Low space on system partition: {percent_used}% used, ' '{free_space} free.') title = ugettext_noop('Low disk space') data = { 'app_icon': 'fa-hdd-o', 'app_name': ugettext_noop('Storage'), 'percent_used': root_info['percent_used'], 'free_space': format_bytes(root_info['free_bytes']) } actions = [{ 'type': 'link', 'class': 'primary', 'text': 'Go to {app_name}', 'url': 'storage:index' }, { 'type': 'dismiss' }] Notification.update_or_create(id='storage-low-disk-space', app_id='storage', severity=severity, title=title, message=message, actions=actions, data=data, group='admin')
def check_dist_upgrade(_): """Check for upgrade to new stable release.""" from plinth.notification import Notification if is_dist_upgrade_enabled(): output = actions.superuser_run('upgrades', ['start-dist-upgrade']) result = json.loads(output) dist_upgrade_started = result['dist_upgrade_started'] reason = result['reason'] if 'found-previous' in reason: logger.info( 'Found previous dist-upgrade. If it was interrupted, it will ' 'be restarted.') elif 'already-' in reason: logger.info('Skip dist upgrade: System is already up-to-date.') elif 'codename-not-found' in reason: logger.warning('Skip dist upgrade: Codename not found in release ' 'file.') elif 'upgrades-not-enabled' in reason: logger.info('Skip dist upgrade: Automatic updates are not ' 'enabled.') elif 'test-not-set' in reason: logger.info('Skip dist upgrade: --test is not set.') elif 'not-enough-free-space' in reason: logger.warning('Skip dist upgrade: Not enough free space in /.') title = gettext_noop('Could not start distribution update') message = gettext_noop( 'There is not enough free space in the root partition to ' 'start the distribution update. Please ensure at least 5 GB ' 'is free. Distribution update will be retried after 24 hours,' ' if enabled.') Notification.update_or_create( id='upgrades-dist-upgrade-free-space', app_id='upgrades', severity='warning', title=title, message=message, actions=[{ 'type': 'dismiss' }], group='admin') elif 'started-dist-upgrade' in reason: logger.info('Started dist upgrade.') title = gettext_noop('Distribution update started') message = gettext_noop( 'Started update to next stable release. This may take a long ' 'time to complete.') Notification.update_or_create(id='upgrades-dist-upgrade-started', app_id='upgrades', severity='info', title=title, message=message, actions=[{ 'type': 'dismiss' }], group='admin') else: logger.warning('Unhandled result of start-dist-upgrade: %s, %s', dist_upgrade_started, reason)
def _show_new_release_notification(self): """When upgraded to new release, show a notification.""" from plinth.notification import Notification try: note = Notification.get('upgrades-new-release') if note.data['version'] == plinth.__version__: # User already has notification for update to this version. It # may be dismissed or not yet dismissed return # User currently has a notification for an older version, update. dismiss = False except KeyError: # Don't show notification for the first version user runs, create # but don't show it. dismiss = True data = { 'version': plinth.__version__, 'app_name': 'Update', 'app_icon': 'fa-refresh' } title = ugettext_noop('FreedomBox Updated') note = Notification.update_or_create( id='upgrades-new-release', app_id='upgrades', severity='info', title=title, body_template='upgrades-new-release.html', data=data, group='admin') note.dismiss(should_dismiss=dismiss)
def _show_schedule_error_notification(repository, is_error, exception=None): """Show or hide a notification related scheduled backup operation.""" from plinth.notification import Notification id_ = 'backups-schedule-error-' + repository.uuid try: note = Notification.get(id_) error_count = note.data['error_count'] except KeyError: error_count = 0 message = ugettext_noop( 'A scheduled backup failed. Past {error_count} attempts for backup ' 'did not succeed. The latest error is: {error_message}') data = { 'app_name': 'translate:' + ugettext_noop('Backups'), 'app_icon': 'fa-files-o', 'error_count': error_count + 1 if is_error else 0, 'error_message': str(exception) } title = ugettext_noop('Error During Backup') actions_ = [{ 'type': 'link', 'class': 'primary', 'text': ugettext_noop('Go to {app_name}'), 'url': 'backups:index' }, { 'type': 'dismiss' }] note = Notification.update_or_create(id=id_, app_id='backups', severity='error', title=title, message=message, actions=actions_, data=data, group='admin') note.dismiss(should_dismiss=not is_error)
def report_failing_drive(id, is_failing): """Show or withdraw notification about failing drive.""" notification_id = 'storage-disk-failure-' + base64.b32encode( id.encode()).decode() from plinth.notification import Notification title = ugettext_noop('Disk failure imminent') message = ugettext_noop( 'Disk {id} is reporting that it is likely to fail in the near future. ' 'Copy any data while you still can and replace the drive.') data = { 'app_icon': 'fa-hdd-o', 'app_name': 'translate:' + ugettext_noop('Storage'), 'id': id } note = Notification.update_or_create(id=notification_id, app_id='storage', severity='error', title=title, message=message, actions=[{ 'type': 'dismiss' }], data=data, group='admin') note.dismiss(should_dismiss=not is_failing)
def fixture_note(): """Fixture to return a valid notification object.""" Notification.objects.all().delete() return Notification.update_or_create(id='test-notification', app_id='test-app', severity='info', title='Test Title', data={'test-key': 'test-value'})
def test_update(note): """Test updating a existing notification.""" note = Notification.get('test-notification') assert note.app_id == 'test-app' assert note.severity == 'info' assert note.title == 'Test Title' assert note.data == {'test-key': 'test-value'} Notification.update_or_create(id='test-notification', app_id='test-app2', severity='error', title='Test Title2', data={'test-key2': 'test-value2'}) note = Notification.get('test-notification') assert note.app_id == 'test-app2' assert note.severity == 'error' assert note.title == 'Test Title2' assert note.data == {'test-key2': 'test-value2'}