Merge lp:~mterry/deja-dup/gio-mount-password into lp:deja-dup/22

Proposed by Michael Terry
Status: Merged
Merged at revision: 1306
Proposed branch: lp:~mterry/deja-dup/gio-mount-password
Merge into: lp:deja-dup/22
Diff against target: 208 lines (+61/-16)
7 files modified
common/Backend.vala (+1/-1)
common/BackendAuto.vala (+1/-1)
common/BackendFile.vala (+44/-1)
common/BackendRackspace.vala (+1/-1)
common/BackendS3.vala (+1/-1)
common/BackendU1.vala (+1/-1)
common/Duplicity.vala (+12/-10)
To merge this branch: bzr merge lp:~mterry/deja-dup/gio-mount-password
Reviewer Review Type Date Requested Status
Ken VanDine Approve
Review via email: mp+98561@code.launchpad.net

This proposal supersedes a proposal from 2012-03-19.

Description of the change

If duplicity is run under sudo (as happens when non-home data is backed up), it can't use the user's remote mount. So it previously just aborted. This branch works around that.

To test:
 * Setup Deja Dup like so:
   - Include "/bin"
   - Make your backup location a remote GVFS location that needs a password, like an FTP server or SSH server
 * Make a backup
 * Try to restore (./deja-dup/deja-dup --restore)

Before the patch:
 * You should get prompted for your root password and it will fail with "Connection failed, please check your password: Login dialog cancelled"

After the patch:
 * You should get *not* get prompted for your root password and it will restore, even though nothing got restored (this is a bug -- I need to make it warn about all the files that didn't get restored)

To post a comment you must log in.
Revision history for this message
Michael Terry (mterry) wrote : Posted in a previous version of this proposal

Hrm, this needs some more thinking. If a user mounts the location first, but does not save the mount info in the keyring, we have no way to get to it. Seems awkward that we're being punished for using the standard GNOME mount infrastructure, but there ya go.

Revision history for this message
Michael Terry (mterry) wrote :

This is still a work in progress because duplicity doesn't currently report permission errors when restoring... This yak is big.

Revision history for this message
Ken VanDine (ken-vandine) wrote :

The diff looks OK to me, however following your steps to test this I got slightly different results. I chose a remote storage location, SSH and backed up /TEST which was only writtable by root. I removed all the files in /TEST and attempted a restore. I didn't get prompted for a password and it reported a successful restore with no warnings. However, no files were actually restored.

Revision history for this message
Michael Terry (mterry) wrote :

Oh! I thought I edited the description of this merge to change what I expected. What you describe is what I expect. :)

The big difference in this branch is just not asking for a password. The restore will have no effect, but will say it succeeded (which is a whole 'nother problem).

Revision history for this message
Ken VanDine (ken-vandine) wrote :

OK, it looks good then. Certainly an improvement over the previous behavior :)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'common/Backend.vala'
--- common/Backend.vala 2012-03-21 02:54:21 +0000
+++ common/Backend.vala 2012-03-21 03:04:22 +0000
@@ -31,7 +31,7 @@
31 public abstract bool is_native(); // must be callable when nothing is mounted, nothing is prepared31 public abstract bool is_native(); // must be callable when nothing is mounted, nothing is prepared
32 public virtual Icon? get_icon() {return null;}32 public virtual Icon? get_icon() {return null;}
3333
34 public abstract string get_location();34 public abstract string get_location(ref bool as_root);
35 public abstract string get_location_pretty(); // short description for user35 public abstract string get_location_pretty(); // short description for user
3636
37 public virtual async bool is_ready(out string when) {when = null; return true;} // must be callable when nothing is mounted, nothing is prepared37 public virtual async bool is_ready(out string when) {when = null; return true;} // must be callable when nothing is mounted, nothing is prepared
3838
=== modified file 'common/BackendAuto.vala'
--- common/BackendAuto.vala 2012-03-21 02:54:21 +0000
+++ common/BackendAuto.vala 2012-03-21 03:04:22 +0000
@@ -40,7 +40,7 @@
40 return false;40 return false;
41 }41 }
4242
43 public override string get_location() {43 public override string get_location(ref bool as_root) {
44 return "invalid";44 return "invalid";
45 }45 }
4646
4747
=== modified file 'common/BackendFile.vala'
--- common/BackendFile.vala 2012-03-21 02:54:21 +0000
+++ common/BackendFile.vala 2012-03-21 03:04:22 +0000
@@ -64,9 +64,52 @@
64 }64 }
6565
66 // Location will be mounted by this time66 // Location will be mounted by this time
67 public override string get_location()67 public override string get_location(ref bool as_root)
68 {68 {
69 var file = get_file_from_settings();69 var file = get_file_from_settings();
70
71 if (as_root && !file.is_native()) {
72 // OK... Root can't use GVFS URIs as-is because it would need access to
73 // our GVFS mounts which are only available on our session dbus. Which
74 // root can't talk to. Possible workarounds:
75 // * Some magic to let root talk to our gvfs daemons (haven't found yet)
76 // * Use FUSE local paths (root also isn't given access to these mounts)
77 // * Have duplicity notice that it needs root to write to a file, and
78 // then restart itself under sudo. But then we'd just hit the same
79 // problem again but now duplicity has to solve it...
80 // * Restore to a temporary folder and move files over with sudo. This
81 // is what we used to always do in older deja-dup. But it had
82 // several problems with consuming the hard drive, especially if the
83 // user had partitioned in ways we didn't expect. Hard to know where
84 // a safe spot is to hoard all the files.
85 // * Pass mount username/password to duplicity as environment variables
86 // and have root do the mount itself. This could work... if we had
87 // a reliable way to get the username/password. We could get it from
88 // keyring (even then, only a guess, since the daemon could have set
89 // the 'object' or 'authtype' fields, which we don't know if it did)
90 // or from a MountOperation. But a user could have mounted it earlier
91 // in session without saving password in keyring. And we can't force
92 // an unmount on the user just so we can remount it.
93 // * Have duplicity try to mount and ask user for password. We'd need
94 // to add functionality to duplicity to allow a conversation between a
95 // driving app like deja-dup and itself, to be able to proxy these
96 // prompts and questions to the user. This would work nicely, but is
97 // a very different interaction model than duplicity uses today.
98 // Much more deja-dup-focused. If we're going down this direction,
99 // there are all sorts of two-way interactions that we could stand to
100 // benefit from. Would require a deep rethink of our driving model.
101 //
102 // So in the absence of an actually good solution, we'll just disable
103 // running under sudo if the location is remote. :( Maybe our
104 // over-eager needs-root algorithm got it wrong anyway. Regardless, this
105 // way the user will get a permissions denied error that will point them
106 // in the direction of trying to restore in a new folder rather than on
107 // top of their running system, which, let's be honest, is probably not
108 // a good idea anyway. BTW, where does Napolean keep his armies?
109 // In his sleevies!
110 as_root = false;
111 }
112
70 return file.get_uri();113 return file.get_uri();
71 }114 }
72115
73116
=== modified file 'common/BackendRackspace.vala'
--- common/BackendRackspace.vala 2012-03-21 02:54:21 +0000
+++ common/BackendRackspace.vala 2012-03-21 03:04:22 +0000
@@ -50,7 +50,7 @@
50 return yield Network.get().can_reach ("http://%s/".printf(RACKSPACE_SERVER));50 return yield Network.get().can_reach ("http://%s/".printf(RACKSPACE_SERVER));
51 }51 }
5252
53 public override string get_location()53 public override string get_location(ref bool as_root)
54 {54 {
55 var settings = get_settings(RACKSPACE_ROOT);55 var settings = get_settings(RACKSPACE_ROOT);
56 var container = get_folder_key(settings, RACKSPACE_CONTAINER_KEY);56 var container = get_folder_key(settings, RACKSPACE_CONTAINER_KEY);
5757
=== modified file 'common/BackendS3.vala'
--- common/BackendS3.vala 2012-03-21 02:54:21 +0000
+++ common/BackendS3.vala 2012-03-21 03:04:22 +0000
@@ -60,7 +60,7 @@
60 return yield Network.get().can_reach ("http://%s/".printf(S3_SERVER));60 return yield Network.get().can_reach ("http://%s/".printf(S3_SERVER));
61 }61 }
6262
63 public override string get_location()63 public override string get_location(ref bool as_root)
64 {64 {
65 var settings = get_settings(S3_ROOT);65 var settings = get_settings(S3_ROOT);
66 66
6767
=== modified file 'common/BackendU1.vala'
--- common/BackendU1.vala 2012-03-21 02:54:21 +0000
+++ common/BackendU1.vala 2012-03-21 03:04:22 +0000
@@ -151,7 +151,7 @@
151 return yield Network.get().can_reach ("https://one.ubuntu.com/");151 return yield Network.get().can_reach ("https://one.ubuntu.com/");
152 }152 }
153153
154 public override string get_location()154 public override string get_location(ref bool as_root)
155 {155 {
156 var settings = get_settings(U1_ROOT);156 var settings = get_settings(U1_ROOT);
157 var folder = get_folder_key(settings, U1_FOLDER_KEY);157 var folder = get_folder_key(settings, U1_FOLDER_KEY);
158158
=== modified file 'common/Duplicity.vala'
--- common/Duplicity.vala 2012-03-21 02:54:21 +0000
+++ common/Duplicity.vala 2012-03-21 03:04:22 +0000
@@ -82,7 +82,6 @@
82 82
83 DuplicityInstance inst;83 DuplicityInstance inst;
84 84
85 string remote;
86 List<string> backend_argv;85 List<string> backend_argv;
87 List<string> saved_argv;86 List<string> saved_argv;
88 List<string> saved_envp;87 List<string> saved_envp;
@@ -166,7 +165,6 @@
166 {165 {
167 // save arguments for calling duplicity again later166 // save arguments for calling duplicity again later
168 mode = original_mode;167 mode = original_mode;
169 this.remote = backend.get_location();
170 this.backend = backend;168 this.backend = backend;
171 saved_argv = new List<string>();169 saved_argv = new List<string>();
172 saved_envp = new List<string>();170 saved_envp = new List<string>();
@@ -206,6 +204,11 @@
206 return 0;204 return 0;
207 }205 }
208206
207 string get_remote ()
208 {
209 return backend.get_location(ref needs_root);
210 }
211
209 void expand_links_in_file(File file, ref List<File> all, bool include, List<File>? seen = null)212 void expand_links_in_file(File file, ref List<File> all, bool include, List<File>? seen = null)
210 {213 {
211 // For symlinks, we want to add the link and its target to the list.214 // For symlinks, we want to add the link and its target to the list.
@@ -558,7 +561,7 @@
558 var cleanup_argv = new List<string>();561 var cleanup_argv = new List<string>();
559 cleanup_argv.append("cleanup");562 cleanup_argv.append("cleanup");
560 cleanup_argv.append("--force");563 cleanup_argv.append("--force");
561 cleanup_argv.append(this.remote);564 cleanup_argv.append(get_remote());
562 565
563 set_status(_("Cleaning up…"));566 set_status(_("Cleaning up…"));
564 connect_and_start(null, null, cleanup_argv);567 connect_and_start(null, null, cleanup_argv);
@@ -572,7 +575,7 @@
572 argv.append("remove-all-but-n-full");575 argv.append("remove-all-but-n-full");
573 argv.append("%d".printf(cutoff));576 argv.append("%d".printf(cutoff));
574 argv.append("--force");577 argv.append("--force");
575 argv.append(this.remote);578 argv.append(get_remote());
576 579
577 set_status(_("Cleaning up…"));580 set_status(_("Cleaning up…"));
578 connect_and_start(null, null, argv);581 connect_and_start(null, null, argv);
@@ -1013,8 +1016,7 @@
1013 case "S3CreateError":1016 case "S3CreateError":
1014 if (text.contains("<Code>BucketAlreadyExists</Code>")) {1017 if (text.contains("<Code>BucketAlreadyExists</Code>")) {
1015 if (((BackendS3)backend).bump_bucket()) {1018 if (((BackendS3)backend).bump_bucket()) {
1016 remote = backend.get_location();1019 if (restart()) // get_remote() will eventually grab new bucket name
1017 if (restart())
1018 return;1020 return;
1019 }1021 }
1020 1022
@@ -1375,21 +1377,21 @@
1375 argv.prepend("full");1377 argv.prepend("full");
1376 argv.append("--volsize=%d".printf(get_volsize()));1378 argv.append("--volsize=%d".printf(get_volsize()));
1377 argv.append(local_arg.get_path());1379 argv.append(local_arg.get_path());
1378 argv.append(remote);1380 argv.append(get_remote());
1379 break;1381 break;
1380 case Operation.Mode.RESTORE:1382 case Operation.Mode.RESTORE:
1381 argv.prepend("restore");1383 argv.prepend("restore");
1382 argv.append("--force");1384 argv.append("--force");
1383 argv.append(remote);1385 argv.append(get_remote());
1384 argv.append(local_arg.get_path());1386 argv.append(local_arg.get_path());
1385 break;1387 break;
1386 case Operation.Mode.STATUS:1388 case Operation.Mode.STATUS:
1387 argv.prepend("collection-status");1389 argv.prepend("collection-status");
1388 argv.append(remote);1390 argv.append(get_remote());
1389 break;1391 break;
1390 case Operation.Mode.LIST:1392 case Operation.Mode.LIST:
1391 argv.prepend("list-current-files");1393 argv.prepend("list-current-files");
1392 argv.append(remote);1394 argv.append(get_remote());
1393 break;1395 break;
1394 }1396 }
1395 }1397 }

Subscribers

People subscribed via source and target branches