← Back to team overview

deja-dup-team team mailing list archive

[Merge] lp:~kvdveer/deja-dup/fix-for-1155645 into lp:deja-dup

 

Ondergetekende has proposed merging lp:~kvdveer/deja-dup/fix-for-1155645 into lp:deja-dup.

Requested reviews:
  Déjà Dup Developers (deja-dup-hackers)
Related bugs:
  Bug #1155500 in Duplicity: "Support OpenstackSwift as a backend"
  https://bugs.launchpad.net/duplicity/+bug/1155500
  Bug #1155645 in Déjà Dup: "Openstack swift support"
  https://bugs.launchpad.net/deja-dup/+bug/1155645

For more details, see:
https://code.launchpad.net/~kvdveer/deja-dup/fix-for-1155645/+merge/153569

Implemented support for Openstack Swift. 
Depends on swift support in duplicity (obviously), which is pending review here: https://code.launchpad.net/~kvdveer/duplicity/fix-for-1155500
-- 
https://code.launchpad.net/~kvdveer/deja-dup/fix-for-1155645/+merge/153569
Your team Déjà Dup Developers is requested to review the proposed merge of lp:~kvdveer/deja-dup/fix-for-1155645 into lp:deja-dup.
=== modified file 'AUTHORS'
--- AUTHORS	2012-06-08 14:15:41 +0000
+++ AUTHORS	2013-03-15 15:10:29 +0000
@@ -26,6 +26,10 @@
            2011 Canonical Ltd
 License: GPL-3+
 
+Files: comon/Backendopenstack.c
+Copyright: 2013 Koert van der Veer <koert@xxxxxxxxxxxx>
+License: GPL-3+
+
 Files: preferences/PreferencesPanel.c
 Copyright: 2010 Intel, Inc
            2011 Michael Terry <mike@xxxxxxxxxxx>

=== modified file 'common/Backend.vala'
--- common/Backend.vala	2012-04-30 00:18:18 +0000
+++ common/Backend.vala	2013-03-15 15:10:29 +0000
@@ -43,13 +43,13 @@
   public static uint64 INFINITE_SPACE = uint64.MAX;
   public virtual async uint64 get_space(bool free = true) {return INFINITE_SPACE;}
   public virtual bool space_can_be_infinite() {return true;}
-  
+
   // Arguments needed only when the particular mode is active
   // If mode == INVALID, arguments needed any time the backup is referenced.
   public virtual void add_argv(ToolJob.Mode mode, ref List<string> argv) {}
-  
+
   public abstract Backend clone();
-  
+
   public static string get_default_type()
   {
     var settings = get_settings();
@@ -58,6 +58,7 @@
     if (backend != "auto" &&
         backend != "s3" &&
         backend != "rackspace" &&
+        backend != "openstack" &&
         backend != "u1" &&
         backend != "file")
       backend = "auto"; // default to auto if string is not known
@@ -74,6 +75,8 @@
       return new BackendU1();
     else if (backend_name == "rackspace")
       return new BackendRackspace();
+    else if (backend_name == "openstack")
+      return new BackendOpenstack();
     else if (backend_name == "file")
       return new BackendFile();
     else

=== added file 'common/BackendOpenstack.vala'
--- common/BackendOpenstack.vala	1970-01-01 00:00:00 +0000
+++ common/BackendOpenstack.vala	2013-03-15 15:10:29 +0000
@@ -0,0 +1,181 @@
+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
+/*
+    This file is part of Déjà Dup.
+    For copyright information, see AUTHORS.
+
+    Déjà Dup 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 3 of the License, or
+    (at your option) any later version.
+
+    Déjà Dup 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 Déjà Dup.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using GLib;
+
+namespace DejaDup {
+
+public const string OPENSTACK_ROOT = "Openstack";
+public const string OPENSTACK_USERNAME_KEY = "username";
+public const string OPENSTACK_CONTAINER_KEY = "container";
+public const string OPENSTACK_TENANT_KEY = "tenant";
+public const string OPENSTACK_AUTHURL_KEY = "authurl";
+
+public class BackendOpenstack : Backend
+{
+  public static Checker get_checker() {
+    return PythonChecker.get_checker("swiftclient");
+  }
+
+  public override Backend clone() {
+    return new BackendOpenstack();
+  }
+
+  public override bool is_native() {
+    return false;
+  }
+
+  public override Icon? get_icon() {
+    return new ThemedIcon("deja-dup-cloud");
+  }
+
+  public override async bool is_ready(out string when) {
+    var settings = get_settings(OPENSTACK_ROOT);
+    var authurl = get_folder_key(settings, OPENSTACK_AUTHURL_KEY);
+    when = _("Backup will begin when a network connection becomes available.");
+    return yield Network.get().can_reach (authurl);
+  }
+
+  public override string get_location(ref bool as_root)
+  {
+    var settings = get_settings(OPENSTACK_ROOT);
+    var container = get_folder_key(settings, OPENSTACK_CONTAINER_KEY);
+    if (container == "") {
+      container = Environment.get_host_name();
+      settings.set_string(OPENSTACK_CONTAINER_KEY, container);
+    }
+    return "swift://%s".printf(container);
+  }
+
+  public override string get_location_pretty()
+  {
+    var settings = get_settings(OPENSTACK_ROOT);
+    var container = settings.get_string(OPENSTACK_CONTAINER_KEY);
+    if (container == "")
+      return _("Openstack Swift");
+    else
+      // Translators: %s is a folder.
+      return _("%s on Openstack Swift").printf(container);
+  }
+
+  string settings_id;
+  string id;
+  string secret_key;
+  public override async void get_envp() throws Error
+  {
+    var settings = get_settings(OPENSTACK_ROOT);
+    settings_id = settings.get_string(OPENSTACK_USERNAME_KEY);
+    id = settings_id == null ? "" : settings_id;
+
+    var authurl = settings.get_string(OPENSTACK_AUTHURL_KEY);
+
+    if (id != "" && secret_key != null) {
+      // We've already been run before and got the key
+      got_secret_key();
+      return;
+    }
+
+    if (id != "") {
+      // First, try user's keyring
+      try {
+        secret_key = yield Secret.password_lookup(Secret.SCHEMA_COMPAT_NETWORK,
+                                                  null,
+                                                  "user", id,
+                                                  "server", authurl,
+                                                  "protocol", "https");
+        if (secret_key != null) {
+          got_secret_key();
+          return;
+        }
+      }
+      catch (Error e) {
+        // fall through to ask_password below
+      }
+    }
+
+    // Didn't find it, so ask user
+    ask_password();
+  }
+
+  async void got_password_reply(MountOperation mount_op, MountOperationResult result)
+  {
+    if (result != MountOperationResult.HANDLED) {
+      envp_ready(false, new List<string>(), _("Permission denied"));
+      return;
+    }
+
+    id = mount_op.username;
+    secret_key = mount_op.password;
+
+    // Save it
+    var remember = mount_op.password_save;
+    if (remember != PasswordSave.NEVER) {
+      string where = (remember == PasswordSave.FOR_SESSION) ?
+                     Secret.COLLECTION_SESSION : Secret.COLLECTION_DEFAULT;
+
+      var settings = get_settings(OPENSTACK_ROOT);
+      var authurl = get_folder_key(settings, OPENSTACK_AUTHURL_KEY);
+      var tenant = get_folder_key(settings, OPENSTACK_TENANT_KEY);
+
+      try {
+        yield Secret.password_store(Secret.SCHEMA_COMPAT_NETWORK,
+                                    where,
+                                    "%s:%s@%s".printf(tenant, id, authurl),
+                                    secret_key,
+                                    null,
+                                    "user", id,
+                                    "server", authurl,
+                                    "protocol", "https");
+      }
+      catch (Error e) {
+        warning("%s\n", e.message);
+      }
+    }
+
+    got_secret_key();
+  }
+
+  void ask_password() {
+    mount_op.reply.connect(got_password_reply);
+    mount_op.ask_password("", id, "",
+                          AskPasswordFlags.NEED_PASSWORD |
+                          AskPasswordFlags.NEED_USERNAME |
+                          AskPasswordFlags.SAVING_SUPPORTED);
+  }
+
+  void got_secret_key() {
+    var settings = get_settings(OPENSTACK_ROOT);
+
+    if (id != settings_id)
+      settings.set_string(OPENSTACK_USERNAME_KEY, id);
+
+    var tenantName = settings.set_string(OPENSTACK_TENANT_KEY, id);
+    var authurl = settings.set_string(OPENSTACK_TENANT_KEY, id);
+
+    List<string> envp = new List<string>();
+    envp.append("SWIFT_TENANTNAME=%s".printf(tenantName));
+    envp.append("SWIFT_AUTHURL=%s".printf(authurl));
+    envp.append("SWIFT_USERNAME=%s".printf(id));
+    envp.append("SWIFT_PASSWORD=%s".printf(secret_key));
+    envp_ready(true, envp);
+  }
+}
+
+} // end namespace
+

=== modified file 'common/Makefile.am'
--- common/Makefile.am	2013-01-27 20:30:52 +0000
+++ common/Makefile.am	2013-03-15 15:10:29 +0000
@@ -39,6 +39,7 @@
 	BackendAuto.vala \
 	BackendFile.vala \
 	BackendRackspace.vala \
+	BackendOpenstack.vala \
 	BackendS3.vala \
 	BackendU1.vala \
 	Checker.vala \

=== modified file 'data/org.gnome.DejaDup.gschema.xml.in'
--- data/org.gnome.DejaDup.gschema.xml.in	2012-10-09 02:35:21 +0000
+++ data/org.gnome.DejaDup.gschema.xml.in	2013-03-15 15:10:29 +0000
@@ -70,6 +70,7 @@
         <choice value='auto'/>
         <choice value='file'/>
         <choice value='rackspace'/>
+        <choice value='openstack'/>
         <choice value='s3'/>
         <choice value='u1'/>
       </choices>
@@ -78,6 +79,7 @@
       <_description>The type of backup location.  If ‘auto’, a default will be chosen based on what is available.</_description>
     </key>
     <child name="rackspace" schema="org.gnome.DejaDup.Rackspace"/>
+    <child name="openstack" schema="org.gnome.DejaDup.Openstack"/>
     <child name="s3" schema="org.gnome.DejaDup.S3"/>
     <child name="u1" schema="org.gnome.DejaDup.U1"/>
     <child name="file" schema="org.gnome.DejaDup.File"/>
@@ -111,6 +113,28 @@
       <_description>This is your username for the Rackspace Cloud Files service.</_description>
     </key>
   </schema>
+  <schema id="org.gnome.DejaDup.Openstack" path="/org/gnome/deja-dup/openstack/">
+    <key name="container" type="s">
+      <default>'$HOSTNAME'</default>
+      <_summary>The Openstack Swift container</_summary>
+      <_description>Which Openstack Swift container to store files in.  This does not need to exist already.  Only legal hostname strings are valid.</_description>
+    </key>
+    <key name="username" type="s">
+      <default>''</default>
+      <_summary>Your Openstack username</_summary>
+      <_description>This is your username for the Openstack Swift service.</_description>
+    </key>
+    <key name="tenant" type="s">
+      <default>''</default>
+      <_summary>Your Openstack tenant</_summary>
+      <_description>This is your tenant for the Openstack Swift service.</_description>
+    </key>
+    <key name="authurl" type="s">
+      <default>''</default>
+      <_summary>Authentication URL</_summary>
+      <_description>This is the Authentication URL, or keystone URL for the Openstack service</_description>
+    </key>
+  </schema>
   <schema id="org.gnome.DejaDup.U1" path="/org/gnome/deja-dup/u1/">
     <key name="folder" type="s">
       <default>'/deja-dup/$HOSTNAME'</default>

=== modified file 'widgets/ConfigLabelLocation.vala'
--- widgets/ConfigLabelLocation.vala	2013-01-27 20:30:52 +0000
+++ widgets/ConfigLabelLocation.vala	2013-03-15 15:10:29 +0000
@@ -28,12 +28,13 @@
   FilteredSettings s3_root;
   FilteredSettings u1_root;
   FilteredSettings rackspace_root;
+  FilteredSettings openstack_root;
 
   public ConfigLabelLocation()
   {
     base(null);
   }
-  
+
   construct {
     img = new Gtk.Image.from_icon_name("folder", Gtk.IconSize.MENU);
     fill_box();
@@ -42,6 +43,7 @@
     watch_key(null, (s3_root = DejaDup.get_settings(S3_ROOT)));
     watch_key(null, (u1_root = DejaDup.get_settings(U1_ROOT)));
     watch_key(null, (rackspace_root = DejaDup.get_settings(RACKSPACE_ROOT)));
+    watch_key(null, (openstack_root = DejaDup.get_settings(OPENSTACK_ROOT)));
     set_from_config.begin();
   }
 

=== modified file 'widgets/ConfigLocation.vala'
--- widgets/ConfigLocation.vala	2012-08-06 22:41:13 +0000
+++ widgets/ConfigLocation.vala	2013-03-15 15:10:29 +0000
@@ -62,6 +62,7 @@
   int index_dav;
   int index_s3 = -2;
   int index_rackspace = -2;
+  int index_openstack = -2;
   int index_u1 = -2;
   int index_cloud_sep = -2;
   int index_ssh;
@@ -112,6 +113,7 @@
     insert_u1();
     insert_s3();
     insert_rackspace();
+    insert_openstack();
 
     // Now insert remote servers
     index_ssh = add_entry(new ThemedIcon.with_default_fallbacks("folder-remote"),
@@ -196,6 +198,14 @@
                               ref index_rackspace, insert_rackspace);
   }
 
+  void insert_openstack() {
+    insert_cloud_if_available("openstack", BackendOpenstack.get_checker(),
+                              new ThemedIcon("deja-dup-cloud"),
+                              _("Openstack Swift"),
+                              new ConfigLocationOpenstack(label_sizes),
+                              ref index_openstack, insert_openstack);
+  }
+
   void insert_cloud_if_available(string id, Checker checker,
                                  Icon icon, string name,
                                  Gtk.Widget w, ref int index,
@@ -411,6 +421,8 @@
       index = index_s3;
     else if (backend == "rackspace")
       index = index_rackspace;
+    else if (backend == "openstack")
+      index = index_openstack;
     else if (backend == "u1")
       index = index_u1;
     else if (backend == "file") {
@@ -501,6 +513,8 @@
       settings.set_string(BACKEND_KEY, "s3");
     else if (index == index_rackspace)
       settings.set_string(BACKEND_KEY, "rackspace");
+    else if (index == index_openstack)
+      settings.set_string(BACKEND_KEY, "openstack");
     else if (index == index_u1)
       settings.set_string(BACKEND_KEY, "u1");
     else if (index == index_ssh)

=== added file 'widgets/ConfigLocationOpenstack.vala'
--- widgets/ConfigLocationOpenstack.vala	1970-01-01 00:00:00 +0000
+++ widgets/ConfigLocationOpenstack.vala	2013-03-15 15:10:29 +0000
@@ -0,0 +1,43 @@
+/* -*- Mode: Vala; indent-tabs-mode: nil; tab-width: 2 -*- */
+/*
+    This file is part of Déjà Dup.
+    For copyright information, see AUTHORS.
+
+    Déjà Dup 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 3 of the License, or
+    (at your option) any later version.
+
+    Déjà Dup 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 Déjà Dup.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using GLib;
+
+namespace DejaDup {
+
+public class ConfigLocationOpenstack : ConfigLocationTable
+{
+  public ConfigLocationOpenstack(Gtk.SizeGroup sg) {
+    Object(label_sizes: sg);
+  }
+
+  construct {
+    add_widget(_("_Username"),
+               new ConfigEntry(DejaDup.OPENSTACK_USERNAME_KEY, DejaDup.OPENSTACK_ROOT));
+    add_widget(_("_Container"),
+               new ConfigFolder(DejaDup.OPENSTACK_CONTAINER_KEY, DejaDup.OPENSTACK_ROOT));
+    add_widget(_("_Authentication URL"),
+               new ConfigFolder(DejaDup.OPENSTACK_AUTHURL_KEY, DejaDup.OPENSTACK_ROOT));
+    add_widget(_("_Tenant name"),
+               new ConfigFolder(DejaDup.OPENSTACK_TENANT_KEY, DejaDup.OPENSTACK_ROOT));
+  }
+}
+
+}
+

=== modified file 'widgets/Makefile.am'
--- widgets/Makefile.am	2012-11-01 09:16:02 +0000
+++ widgets/Makefile.am	2013-03-15 15:10:29 +0000
@@ -52,6 +52,7 @@
 	ConfigLocationFile.vala \
 	ConfigLocationFTP.vala \
 	ConfigLocationRackspace.vala \
+	ConfigLocationOpenstack.vala \
 	ConfigLocationS3.vala \
 	ConfigLocationSSH.vala \
 	ConfigLocationSMB.vala \


Follow ups