El Sun, 16-05-2010 a las 11:30 -0700, Thomas C Gilliard escribió: > Bernie; > > Will you make a .xo or rpm of your backup for standalone instances of > Soas?
All we need is a new control panel item in Sugar and add 3 scripts to ds-backup-client. I'm attaching patches to do both things. You can test this functionality in os180py. The current implementation works, but is way too crude for upstreaming it. My TODO list contains: 1) Discuss UI refinements proposed by Eben (see his post to sugar-devel) 2) Integrate the USB backup/restore functionality developed by Esteban for LATU. 3) Address the concerns of Martin Langhoff regarding destroying the current journal contents on restore. > How would I convert it to a .xo file? > Is there a reference I should consult? > > I am running from the command line now. Documentation for creating bundles is here: http://wiki.sugarlabs.org/go/Development_Team/Almanac/Activity_Bundles But I feel that backup/restore should be core Sugar functionality, not implemented as an activity. -- // Bernie Innocenti - http://codewiz.org/ \X/ Sugar Labs - http://sugarlabs.org/
>From 5a83859a66d5fb55e7587e4890b37cae13f39735 Mon Sep 17 00:00:00 2001 From: Martin Abente <mabe...@paraguayeduca.org> Date: Fri, 9 Apr 2010 14:18:42 -0400 Subject: [PATCH] Backup & Restore front end for control panel Organization: Paraguay Educa Backported from 0.88 Signed-off-by: Martin Abente <mabe...@paraguayeduca.org> --- configure.ac | 1 + data/icons/Makefile.am | 1 + data/icons/module-journalmanagement.svg | 127 +++++++++++ extensions/cpsection/Makefile.am | 2 +- extensions/cpsection/journalmanagement/Makefile.am | 6 + extensions/cpsection/journalmanagement/__init__.py | 22 ++ extensions/cpsection/journalmanagement/model.py | 78 +++++++ extensions/cpsection/journalmanagement/view.py | 236 ++++++++++++++++++++ 8 files changed, 472 insertions(+), 1 deletions(-) create mode 100644 data/icons/module-journalmanagement.svg create mode 100644 extensions/cpsection/journalmanagement/Makefile.am create mode 100644 extensions/cpsection/journalmanagement/__init__.py create mode 100644 extensions/cpsection/journalmanagement/model.py create mode 100644 extensions/cpsection/journalmanagement/view.py diff --git a/configure.ac b/configure.ac index 479056d..40442c6 100644 --- a/configure.ac +++ b/configure.ac @@ -53,6 +53,7 @@ extensions/cpsection/aboutcomputer/Makef extensions/cpsection/aboutme/Makefile extensions/cpsection/datetime/Makefile extensions/cpsection/frame/Makefile +extensions/cpsection/journalmanagement/Makefile extensions/cpsection/keyboard/Makefile extensions/cpsection/language/Makefile extensions/cpsection/modemconfiguration/Makefile diff --git a/data/icons/Makefile.am b/data/icons/Makefile.am index e1f8fa7..b982f2e 100644 --- a/data/icons/Makefile.am +++ b/data/icons/Makefile.am @@ -5,6 +5,7 @@ sugar_DATA = \ module-about_my_computer.svg \ module-date_and_time.svg \ module-frame.svg \ + module-journalmanagement.svg \ module-keyboard.svg \ module-language.svg \ module-modemconfiguration.svg \ diff --git a/data/icons/module-journalmanagement.svg b/data/icons/module-journalmanagement.svg new file mode 100644 index 0000000..9250c6f --- /dev/null +++ b/data/icons/module-journalmanagement.svg @@ -0,0 +1,127 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<svg + xmlns:dc="http://purl.org/dc/elements/1.1/" + xmlns:cc="http://creativecommons.org/ns#" + xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" + xmlns:svg="http://www.w3.org/2000/svg" + xmlns="http://www.w3.org/2000/svg" + xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" + xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" + enable-background="new 0 0 55 55" + height="55px" + id="Layer_1" + version="1.1" + viewBox="0 0 55 55" + width="55px" + x="0px" + xml:space="preserve" + y="0px" + sodipodi:version="0.32" + inkscape:version="0.46" + sodipodi:docname="journalmanagement.svg" + inkscape:output_extension="org.inkscape.output.svg.inkscape"><sodipodi:namedview + inkscape:window-height="827" + inkscape:window-width="1440" + inkscape:pageshadow="2" + inkscape:pageopacity="0.0" + guidetolerance="10.0" + gridtolerance="10.0" + objecttolerance="10.0" + borderopacity="1.0" + bordercolor="#666666" + pagecolor="#ffffff" + id="base" + showgrid="false" + inkscape:zoom="8.9818182" + inkscape:cx="7.7378543" + inkscape:cy="27.5" + inkscape:window-x="0" + inkscape:window-y="25" + inkscape:current-layer="Layer_1" /><metadata + id="metadata35"><rdf:RDF><cc:Work + rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type + rdf:resource="http://purl.org/dc/dcmitype/StillImage" /></cc:Work></rdf:RDF></metadata><defs + id="defs33"><inkscape:perspective + sodipodi:type="inkscape:persp3d" + inkscape:vp_x="0 : 27.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_z="55 : 27.5 : 1" + inkscape:persp3d-origin="27.5 : 18.333333 : 1" + id="perspective37" /><inkscape:perspective + id="perspective12" + inkscape:persp3d-origin="27.5 : 18.333333 : 1" + inkscape:vp_z="55 : 27.5 : 1" + inkscape:vp_y="0 : 1000 : 0" + inkscape:vp_x="0 : 27.5 : 1" + sodipodi:type="inkscape:persp3d" /></defs> + +<g + display="block" + id="document-save" + transform="matrix(1.2198714,0,0,1.0017443,-2.2062535,-2.4418416)" + style="display:block"> + <g + id="g4"> + <g + id="g6"> + <g + id="g8"> + <path + d="M 6.736,49.002 L 31.256,49.002 C 33.481,49.002 34.695,47.555 34.695,45.561 L 34.695,18.281 C 34.695,16.551 32.963,14.84 31.256,14.84 L 26.867,14.84" + id="path10" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + </g> + </g> + <g + id="g12"> + <g + id="g14"> + <path + d="M 26.867,38.592 C 26.867,40.428 25.522,41.793 23.426,42.639 L 6.736,49.002 L 6.736,14.84 L 23.426,6.241 C 25.654,5.847 26.867,7.081 26.867,9.075 L 26.867,38.592 z" + id="path16" + style="fill:#ffffff;stroke:#010101;stroke-width:3.5;stroke-linecap:round;stroke-linejoin:round" /> + </g> + </g> + <path + d="M 9.424,42.607 C 9.424,42.607 8.073,42.064 6.722,42.064 C 5.371,42.064 4.019,42.607 4.019,42.607" + id="path18" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="M 9.424,32.006 C 9.424,32.006 8.185,31.463 6.609,31.463 C 5.032,31.463 4.019,32.006 4.019,32.006" + id="path20" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + <path + d="M 9.424,21.678 C 9.424,21.678 8.299,21.134 6.497,21.134 C 4.695,21.134 4.019,21.678 4.019,21.678" + id="path22" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + + <line + x1="13.209" + x2="13.209" + y1="46.533001" + y2="11.505" + id="line24" + style="fill:none;stroke:#010101;stroke-width:2.25;stroke-linecap:round;stroke-linejoin:round" /> + + <g + id="g26"> + + + </g> + </g> +</g><rect + y="28.864494" + x="28.753164" + height="22.87829" + width="23.546305" + id="rect2668" + style="fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:2.99260712;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" /><g + id="view-expand" + display="block" + transform="matrix(0.4680612,0,0,0.4482681,27.768809,28.143274)" + style="fill:#000000;display:block"> + <path + id="path5" + d="M 4.875,5 L 4.875,50 L 49.875,50 L 49.875,5 L 4.875,5 z M 23.638,44.051 L 12.574,44.051 C 12.503,44.051 12.433,44.038 12.364,44.03 C 12.322,44.025 12.28,44.026 12.238,44.017 C 12.205,44.01 12.174,43.997 12.141,43.989 C 12.062,43.968 11.983,43.949 11.907,43.918 C 11.894,43.912 11.882,43.903 11.869,43.897 C 11.779,43.857 11.691,43.813 11.607,43.757 C 11.511,43.694 11.42,43.62 11.338,43.538 C 11.255,43.455 11.181,43.363 11.116,43.266 C 11.086,43.22 11.065,43.17 11.04,43.122 C 11.012,43.07 10.98,43.02 10.957,42.965 C 10.925,42.889 10.905,42.809 10.885,42.73 C 10.877,42.7 10.864,42.67 10.858,42.639 C 10.839,42.541 10.831,42.443 10.829,42.343 C 10.829,42.328 10.825,42.315 10.825,42.3 L 10.825,31.236 C 10.825,30.267 11.608,29.485 12.574,29.485 C 13.542,29.485 14.325,30.267 14.325,31.236 L 14.325,38.075 L 22.337,30.06 C 23.021,29.378 24.129,29.378 24.813,30.06 C 25.495,30.744 25.495,31.852 24.813,32.537 L 16.8,40.549 L 23.638,40.549 L 23.638,40.552 C 24.604,40.552 25.388,41.334 25.388,42.3 C 25.389,43.267 24.604,44.051 23.638,44.051 z M 42.573,25.114 C 41.605,25.114 40.822,24.331 40.822,23.363 L 40.822,16.523 L 31.809,25.536 C 31.467,25.878 31.019,26.049 30.571,26.049 C 30.124,26.049 29.675,25.878 29.334,25.536 C 28.651,24.852 28.651,23.745 29.334,23.061 L 38.345,14.049 L 31.511,14.049 C 30.545,14.049 29.76,13.264 29.76,12.298 C 29.76,11.332 30.545,10.547 31.511,10.547 L 42.573,10.547 C 42.677,10.547 42.782,10.559 42.885,10.578 C 42.892,10.579 42.9,10.579 42.906,10.58 C 42.961,10.591 43.012,10.611 43.066,10.627 C 43.124,10.644 43.182,10.657 43.238,10.68 C 43.27,10.693 43.3,10.713 43.331,10.729 C 43.402,10.763 43.475,10.796 43.541,10.841 C 43.598,10.878 43.646,10.924 43.697,10.968 C 43.734,10.999 43.774,11.025 43.809,11.059 C 43.856,11.106 43.892,11.16 43.933,11.211 C 43.963,11.25 43.999,11.285 44.027,11.326 C 44.088,11.417 44.137,11.513 44.178,11.611 C 44.181,11.617 44.185,11.622 44.188,11.628 C 44.222,11.711 44.245,11.796 44.265,11.883 C 44.272,11.908 44.283,11.933 44.287,11.959 C 44.299,12.02 44.301,12.083 44.306,12.145 C 44.311,12.196 44.322,12.247 44.322,12.298 L 44.324,23.363 C 44.324,24.332 43.54,25.114 42.573,25.114 z" + style="fill:#000000" /> +</g></svg> \ No newline at end of file diff --git a/extensions/cpsection/Makefile.am b/extensions/cpsection/Makefile.am index 73e5164..fe6b46b 100644 @@ -1,5 +1,15 @@ -SUBDIRS = aboutme aboutcomputer datetime frame keyboard language \ - modemconfiguration network power updater +SUBDIRS = + aboutme \ + aboutcomputer \ + datetime \ + frame \ + journalmanagement \ + keyboard \ + language \ + modemconfiguration \ + network \ + power \ + updater sugardir = $(pkgdatadir)/extensions/cpsection sugar_PYTHON = __init__.py diff --git a/extensions/cpsection/journalmanagement/Makefile.am b/extensions/cpsection/journalmanagement/Makefile.am new file mode 100644 index 0000000..ed68aa7 --- /dev/null +++ b/extensions/cpsection/journalmanagement/Makefile.am @@ -0,0 +1,6 @@ +sugardir = $(pkgdatadir)/extensions/cpsection/journalmanagement + +sugar_PYTHON = \ + __init__.py \ + model.py \ + view.py diff --git a/extensions/cpsection/journalmanagement/__init__.py b/extensions/cpsection/journalmanagement/__init__.py new file mode 100644 index 0000000..6eace00 --- /dev/null +++ b/extensions/cpsection/journalmanagement/__init__.py @@ -0,0 +1,22 @@ +# Copyright (C) 2010 Paraguay Educa, Martin Abente +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + +from gettext import gettext as _ + +CLASS = 'JournalManagement' +ICON = 'module-journalmanagement' +TITLE = _('Journal Management') + diff --git a/extensions/cpsection/journalmanagement/model.py b/extensions/cpsection/journalmanagement/model.py new file mode 100644 index 0000000..811bdfb --- /dev/null +++ b/extensions/cpsection/journalmanagement/model.py @@ -0,0 +1,78 @@ +# Copyright (C) 2010 Paraguay Educa, Martin Abente, Bernie Innocenti +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + +import os +import gobject +import glib +import gio +import logging + +BYTES_TO_READ = 100 + +class JournalManagementModel(gobject.GObject): + + __gtype_name__ = 'JournalManagementModel' + + __gsignals__ = { + 'journal-management-running' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([str])), + 'journal-management-started' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'journal-management-finished' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])), + 'journal-management-failed' : (gobject.SIGNAL_RUN_FIRST, gobject.TYPE_NONE, ([])) + } + + def __init__(self): + gobject.GObject.__init__(self) + + self._running = False + self._backup_script_path = ['/usr/bin/journal-backup'] + self._restore_script_path = ['/usr/bin/journal-restore'] + + def do_backup(self): + self.run_cmd_async(self._backup_script_path) + + def do_restore(self): + self.run_cmd_async(self._restore_script_path) + + def report_process_status(self, stream, result): + data = stream.read_finish(result) + + if len(data): + self.emit('journal-management-running', data) + stream.read_async(BYTES_TO_READ, self.report_process_status) + + def run_cmd_async(self, cmd): + if self._running == False: + try: + pid, stdin, stdout, stderr = glib.spawn_async(cmd, flags=glib.SPAWN_DO_NOT_REAP_CHILD, standard_output=True) + gobject.child_watch_add(pid, _handle_process_end, (self)) + except Exception: + self.emit('journal-management-failed') + else: + stdin_stream = gio.unix.InputStream(stdout, True) + stdin_stream.read_async(BYTES_TO_READ, self.report_process_status) + + self._running = True + self.emit('journal-management-started') + +def _handle_process_end(pid, condition, myself): + myself._running = False + + if os.WIFEXITED(condition) and\ + os.WEXITSTATUS(condition) == 0: + myself.emit('journal-management-finished') + else: + myself.emit('journal-management-failed') + diff --git a/extensions/cpsection/journalmanagement/view.py b/extensions/cpsection/journalmanagement/view.py new file mode 100644 index 0000000..ae3194c --- /dev/null +++ b/extensions/cpsection/journalmanagement/view.py @@ -0,0 +1,236 @@ +# Copyright (C) 2010 Paraguay Educa, Martin Abente +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US. + +import gtk +import gobject +import logging +from gettext import gettext as _ + +from jarabe.model.session import get_session_manager + +from sugar.graphics import style +from sugar.graphics.alert import Alert +from sugar.graphics.icon import Icon + +from jarabe.controlpanel.sectionview import SectionView + +from model import JournalManagementModel + +class JournalManagement(SectionView): + def __init__(self, model, alerts): + SectionView.__init__(self) + + self._model = JournalManagementModel() + self._model.connect('journal-management-running', self._set_update_log) + self._model.connect('journal-management-started', self._set_status_started) + self._model.connect('journal-management-finished', self._set_status_finished) + self._model.connect('journal-management-failed', self._set_status_failed) + + self.restart_alerts = alerts + self._showing_alert = False + self._process_name = None + self._needs_restart = True + + self.set_border_width(style.DEFAULT_SPACING) + self.set_spacing(style.DEFAULT_SPACING) + self._group = gtk.SizeGroup(gtk.SIZE_GROUP_HORIZONTAL) + + self._vbox = gtk.VBox() + + self._setup_options() + self._setup_status_info() + self._setup_more_info() + + self._vbox.show() + self.pack_start(self._vbox, expand=True) + + def _setup_options(self): + self._setup_separator(_('Options')) + + self._setup_option(_('Backup'), \ + _('Save your Journal to the School Server'), \ + self._pre_start_backup_cb) + + self._setup_option(_('Restore'), \ + _('Restore your Journal to the last backup'), \ + self._pre_start_restore_cb) + + def _setup_option(self, button_text, description_text, button_callback): + option_hbox = gtk.HBox() + + button = gtk.Button(label=button_text) + button.connect('pressed', button_callback) + button.show() + option_hbox.pack_start(button, expand=True, fill=True) + + label = gtk.Label(description_text) + label.show() + option_hbox.pack_start(label, expand=True, fill=True) + + option_hbox.show() + self._vbox.pack_start(option_hbox, expand=False, padding=5) + + def _setup_expander(self): + expander = gtk.Expander(_('Show')) + expander.connect("notify::expanded", self._log_menu_control) + expander.show() + + self._vbox.pack_start(expander, expand=False) + + def _setup_more_info(self): + self._setup_separator(_('Log')) + self._setup_expander() + self._setup_log() + + def _setup_status_info(self): + self._setup_separator(_('Status')) + + self._status_label = gtk.Label(_('No process is running')) + self._status_label.show() + + self._vbox.pack_start(self._status_label, expand=False, fill=False) + + def _setup_log(self): + self._log_vbox = gtk.VBox() + + scrolled_window = gtk.ScrolledWindow() + scrolled_window.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC) + self._log_vbox.pack_start(scrolled_window, expand=True, padding= 10) + + self._log_view = gtk.TextView() + self._log_view.set_editable(False) + self._log_buffer = self._log_view.get_buffer() + scrolled_window.add(self._log_view) + + self._vbox.pack_start(self._log_vbox, expand=True) + + def _setup_separator(self, label_text): + separator_vbox = gtk.VBox() + + separator = gtk.HSeparator() + separator.show() + separator_vbox.pack_start(separator, expand=False) + + label = gtk.Label(label_text) + label.set_alignment(0, 0) + label.show() + separator_vbox.pack_start(label, expand=False) + + separator_vbox.show() + self._vbox.pack_start(separator_vbox, expand=False, padding=10) + + def _log_menu_control(self, expander, data= None): + if expander.get_expanded(): + self._log_vbox.show_all() + else: + self._log_vbox.hide() + + def _pre_start_restore_cb(self, button, data= None): + self._show_alert(_('Restore Warning!'), \ + _('You are about to delete all your journal, are you sure?'), \ + self._response_restore_cb) + + def _response_restore_cb(self, alert, response_id): + if response_id == gtk.RESPONSE_APPLY: + self._process_name = _('Restore') + self._needs_restart = True + self._model.do_restore() + + self._destroy_alert(alert) + + def _pre_start_backup_cb(self, button, data= None): + self._show_alert(_('Backup Warning!'), \ + _('This process could take several minutes, are you sure?'), \ + self._response_backup_cb) + + def _response_backup_cb(self, alert, response_id): + if response_id == gtk.RESPONSE_APPLY: + self._process_name = _('Backup') + self._needs_restart = False + self._model.do_backup() + + self._destroy_alert(alert) + + def _set_update_log(self, model, data): + self._log_buffer.insert(self._log_buffer.get_end_iter(), data) + self._log_view.scroll_to_iter(self._log_buffer.get_end_iter(), 0) + + def _set_status_started(self, model, data=None): + self._status_label.set_text(self._process_name + ' ' +\ + _('is running, please wait...')) + + self._hack_hide_toolbar_buttons() + + def _set_status_finished(self, model, data=None): + self._status_label.set_text(self._process_name + ' ' + \ + _('has finished, please check the logs.')) + + if self._needs_restart == True: + self._show_alert(self._process_name + ' ' + \ + _('Warning!'), \ + _('The process has finished, Sugar will restart now.'), \ + self._post_process_restart_cb, \ + True) + else: + self._hack_show_toolbar_buttons() + + def _post_process_restart_cb(self, alert, responde_id): + session_manager = get_session_manager() + session_manager.logout() + + def _set_status_failed(self, model, data=None): + self._status_label.set_text(self._process_name + ' ' +\ + _('has failed.')) + + self._hack_show_toolbar_buttons() + + def _show_alert(self, title, msg, response_listener_cb, only_yes= False): + if self._showing_alert == False and \ + self._model._running == False: + alert = Alert() + alert.props.title = title + alert.props.msg = msg + + if only_yes == False: + icon = Icon(icon_name='dialog-cancel') + alert.add_button(gtk.RESPONSE_CANCEL, _('No'), icon) + icon.show() + + icon = Icon(icon_name='dialog-ok') + alert.add_button(gtk.RESPONSE_APPLY, _('Yes'), icon) + icon.show() + + alert.connect('response', response_listener_cb) + alert.show() + + self._vbox.pack_start(alert, False) + self._vbox.reorder_child(alert, 0) + self._showing_alert = True + + def _destroy_alert(self, alert): + self._vbox.remove(alert) + self._showing_alert = False + + def _hack_show_toolbar_buttons(self): + panel_control = self.get_toplevel() + panel_control._section_toolbar.cancel_button.show() + panel_control._section_toolbar.accept_button.show() + + def _hack_hide_toolbar_buttons(self): + panel_control = self.get_toplevel() + panel_control._section_toolbar.cancel_button.hide() + panel_control._section_toolbar.accept_button.hide() + -- 1.6.0.4
>From 39131d8c3d3e2c5bf069b81e873c9b88b66b87ab Mon Sep 17 00:00:00 2001 From: Bernie Innocenti <ber...@codewiz.org> Date: Fri, 9 Apr 2010 17:40:12 -0300 Subject: [PATCH] Add journal-{backup,backup-list,restore} Organization: Sugar Labs Foundation X-Subversion: sucks Signed-off-by: Bernie Innocenti <ber...@codewiz.org> --- Makefile.build | 3 +++ client/journal-backup | 43 +++++++++++++++++++++++++++++++++++++++++++ client/journal-backup-list | 38 ++++++++++++++++++++++++++++++++++++++ client/journal-restore | 30 ++++++++++++++++++++++++++++++ ds-backup.spec.in | 8 +++++++- 5 files changed, 121 insertions(+), 1 deletions(-) create mode 100644 client/journal-backup create mode 100644 client/journal-backup-list create mode 100644 client/journal-restore diff --git a/Makefile.build b/Makefile.build index 2e1712e..f6cd00f 100644 --- a/Makefile.build +++ b/Makefile.build @@ -5,6 +5,9 @@ install-client: install -D -d $(DESTDIR)/usr/bin install -D client/ds-backup.py $(DESTDIR)/usr/bin/ install -D client/ds-backup.sh $(DESTDIR)/usr/bin/ + install -D client/journal-backup $(DESTDIR)/usr/bin/ + install -D client/journal-backup-list $(DESTDIR)/usr/bin/ + install -D client/journal-restore $(DESTDIR)/usr/bin/ install -D -d $(DESTDIR)/etc install -D -m 644 client/cron-ds-backup.conf $(DESTDIR)/etc/cron.d/ds-backup diff --git a/client/journal-backup b/client/journal-backup new file mode 100644 index 0000000..54ca743 --- /dev/null +++ b/client/journal-backup @@ -0,0 +1,43 @@ +#!/bin/bash +# Copyright (C) 2009 Daniel Drake <d...@laptop.org> +# Copyright (C) 2010 Paraguay Educa <http://paraguayeduca.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + +echo "Starting" + +# make the lock dir if needed +# we will keep the (empty) file around +if [ ! -d ~/.sugar/default/lock ]; then + mkdir ~/.sugar/default/lock || exit 1; +fi +LOCKFILE=~/.sugar/default/lock/ds-backup.run +echo "Locking" + +# this fails when (this script is) copied to a usb stick +#flock -n $LOCKFILE `dirname $0 `/ds-backup.py +#flock -n $LOCKFILE /usr/bin/ds-backup.py +echo "Backing up" +python /usr/bin/ds-backup.py + +EXITCODE=$? + +if [[ ${EXITCODE} != 0 ]]; then + echo "Sorry, it failed"; + exit -1; +fi + +echo "Great, it is done" +exit 0 diff --git a/client/journal-backup-list b/client/journal-backup-list new file mode 100644 index 0000000..da71ce7 --- /dev/null +++ b/client/journal-backup-list @@ -0,0 +1,38 @@ +#!/bin/bash +# Copyright (C) 2009 Daniel Drake <d...@laptop.org> +# Copyright (C) 2010 Paraguay Educa <http://paraguayeduca.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + +sn=$(</ofw/mfg-data/SN) +output=$(echo "ls -1" | sftp -F /dev/null -oPasswordAuthentication=no -oStrictHostKeyChecking=no -oUser=${sn} -oIdentityFile=/home/olpc/.sugar/default/owner.key schoolserver) + +EXITCODE=$? + +if [[ $? != 0 ]]; then + exit ${EXITCODE} +fi + +IFS="" + +for line in ${output}; do + if [[ ${line:0:10} != "datastore-" || ${line} == "datastore-latest" ]]; then + continue + fi + echo " - ${line:10}" +done + +exit ${EXITCODE} + diff --git a/client/journal-restore b/client/journal-restore new file mode 100644 index 0000000..c69ac44 --- /dev/null +++ b/client/journal-restore @@ -0,0 +1,30 @@ +#!/bin/bash +# Copyright (C) 2009 Daniel Drake <d...@laptop.org> +# Copyright (C) 2010 Paraguay Educa <http://paraguayeduca.org> +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 US + +to_restore=${1:-current} + +pkill -f -x "python /usr/bin/datastore-service" + +sn=$(</ofw/mfg-data/SN) +sshcmd="ssh -F /dev/null -o 'PasswordAuthentication no' -o 'StrictHostKeyChecking no' -i /home/olpc/.sugar/default/owner.key -l ${sn}" +rsync -z -rlt --delete-before -e "${sshcmd}" --progress \ + "schoolserver:datastore-${to_restore}/" \ + "/home/olpc/.sugar/default/datastore/" + +exit $? + diff --git a/ds-backup.spec.in b/ds-backup.spec.in index fde1f60..5a94837 100644 --- a/ds-backup.spec.in +++ b/ds-backup.spec.in @@ -31,6 +31,9 @@ Requires: sugar-datastore Requires: sugar Requires: vixie-cron +# For /usr/bin/flock +Requires: util-linux-ng + %package server Summary: OLPC DS backup & restore server @@ -78,6 +81,9 @@ chkconfig --level 345 incrond on %config %{_sysconfdir}/cron.d/ds-backup %{_bindir}/ds-backup.py %{_bindir}/ds-backup.sh +%{_bindir}/journal-backup +%{_bindir}/journal-backup-list +%{_bindir}/journal-restore %files server %defattr(-,root,root,-) @@ -90,7 +96,7 @@ chkconfig --level 345 incrond on %{_bindir}/ds-postprocess.py %{_bindir}/ds-cleanup.sh %{_bindir}/ds-cleanup.py -/var/www/ds-backup/backup-available.py +%{_var}/www/ds-backup/backup-available.py* %attr(700, apache, apache) %dir %{_localstatedir}/lib/ds-backup/recentclients %attr(777, nobody, nobody) %dir %{_localstatedir}/lib/ds-backup/completion -- 1.7.0.1
_______________________________________________ Sugar-devel mailing list Sugar-devel@lists.sugarlabs.org http://lists.sugarlabs.org/listinfo/sugar-devel