Merge ~jibel/ubiquity:active_directory into ubiquity:master
- Git
- lp:~jibel/ubiquity
- active_directory
- Merge into master
Status: | Merged | ||||
---|---|---|---|---|---|
Merged at revision: | b153322202eba093b3a0b5d96ef3731a373e682a | ||||
Proposed branch: | ~jibel/ubiquity:active_directory | ||||
Merge into: | ubiquity:master | ||||
Diff against target: |
1436 lines (+849/-274) 8 files modified
debian/changelog (+8/-0) debian/ubiquity.templates (+81/-1) gui/gtk/stepUserInfo.ui (+532/-269) scripts/plugininstall.py (+70/-0) tests/test_usersetup.py (+1/-0) ubiquity/components/plugininstall.py (+2/-0) ubiquity/frontend/gtk_ui.py (+9/-1) ubiquity/plugins/ubi-usersetup.py (+146/-3) |
||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Matthew Paul Thomas (community) | design | Needs Fixing | |
Iain Lane | Approve | ||
Review via email:
|
Commit message
Support for Active directory to the GTK UI.
Description of the change

Jean-Baptiste Lallement (jibel) wrote : | # |
@Laney, thanks for the review.
Here is the design review https:/
The comments from mpt have all been addressed.

Jean-Baptiste Lallement (jibel) : | # |

Jean-Baptiste Lallement (jibel) wrote : | # |
Branch as been updated.

Iain Lane (laney) wrote : | # |
Looks ok to me, thanks for the updates.
I'll email mpt to give a design 'approve', should be a quick job given it's already been through review.
One thing though, can you please get seb128 to check all the translations are ok here? It's weird/difficult with ubiquity and Seb's helped me fix things there before.

Iain Lane (laney) wrote : | # |
I saw this got merged without the two things I requested, but I would still appreciate them happening.

Matthew Paul Thomas (mpt) wrote : | # |
Thanks for working on the design changes I requested:
❓ Move the Active Directory checkbox down so that it doesn’t look like part of the password group: commented as “Done”, but not shown in the screenshot.
✔ Add an explanatory caption below the checkbox label: Done.
✘ Move the “Test” button to the right of the field to better explain what it was for: Done, but unfortunately at the same time it was renamed to “Test connection”. Ubuntu buttons use Title Case, so this should be either “Test”, or “Test Connection” with a capital C.
✘ If connection fails, tell people to visit ubuntu.

Iain Lane (laney) wrote : | # |
Thanks mpt.
For me it's OK to follow up on those requests with a separate upload, if you'd prefer to do that, so that the stuff we have now can get out there for testing.
Same with the translations, given Seb is not around right now.

Jean-Baptiste Lallement (jibel) wrote : | # |
@mpt, thanks for your comment.
1. The AD checkbox has been moved outside of the GtkBox containing the 2 radio buttons. It follows the same space than other pages. padding of 6px for the alignment that contains it, no margin for the widget. However, I added a margin of 6px between the group of radio buttons and the checkbox to make the separation clearer.
3. Fixed.
4. Fixed.
The gdoc has been updated.

Jean-Baptiste Lallement (jibel) wrote : | # |
PR https:/

Jean-Baptiste Lallement (jibel) wrote : | # |
submitted https:/
Preview Diff
1 | diff --git a/debian/changelog b/debian/changelog |
2 | index 286dc17..739798c 100644 |
3 | --- a/debian/changelog |
4 | +++ b/debian/changelog |
5 | @@ -1,3 +1,11 @@ |
6 | +ubiquity (20.10.10) UNRELEASED; urgency=medium |
7 | + |
8 | + [ Didier Roche ] |
9 | + [ Jean-Baptiste Lallement ] |
10 | + * AD integration for GTK UI. |
11 | + |
12 | + -- Jean-Baptiste Lallement <jean-baptiste.lallement@ubuntu.com> Tue, 25 Aug 2020 10:06:29 +0200 |
13 | + |
14 | ubiquity (20.10.9) groovy; urgency=medium |
15 | |
16 | * gtk_ui, prepare: Run 'apt update' before installing OEM metapackages. We |
17 | diff --git a/debian/ubiquity.templates b/debian/ubiquity.templates |
18 | index 89a32e1..eb6d724 100644 |
19 | --- a/debian/ubiquity.templates |
20 | +++ b/debian/ubiquity.templates |
21 | @@ -656,6 +656,10 @@ Template: ubiquity/install/bootloader |
22 | Type: text |
23 | _Description: Configuring boot loader... |
24 | |
25 | +Template: ubiquity/install/activedirectory |
26 | +Type: text |
27 | +_Description: Configuring Active Directory... |
28 | + |
29 | Template: ubiquity/install/apt_clone_save |
30 | Type: text |
31 | _Description: Saving installed packages... |
32 | @@ -770,6 +774,14 @@ _Description: Error restoring installed applications |
33 | installation will continue, but you may have to manually reinstall some |
34 | applications after the computer reboots. |
35 | |
36 | +Template: ubiquity/install/broken_active_directory |
37 | +Type: error |
38 | +_Description: Error configuring connection to Active Directory |
39 | + Sorry, Active Directory can't be set up at the moment. Once your system is up |
40 | + and running, visit |
41 | + <a href="https://discourse.ubuntu.com/t/service-sssd/11579">ubuntu.com/activedirectory</a> |
42 | + for help. |
43 | + |
44 | Template: ubiquity/install/md5_check |
45 | Type: boolean |
46 | Default: true |
47 | @@ -1637,4 +1649,72 @@ _Description: |
48 | |
49 | Template: ubiquity/zfs_keystore_key |
50 | Type: password |
51 | -_Description: Key to secure the keystore on ZFS installations |
52 | \ No newline at end of file |
53 | +_Description: Key to secure the keystore on ZFS installations |
54 | + |
55 | +Template: ubiquity/login_use_directory |
56 | +Type: text |
57 | +_Description: Authenticate against a directory |
58 | + |
59 | +Template: ubiquity/directory_domain |
60 | +Type: text |
61 | +_Description: Active Directory domain name |
62 | + |
63 | +Template: ubiquity/directory_user |
64 | +Type: text |
65 | +_Description: Administrator to join the domain |
66 | + |
67 | +Template: ubiquity/directory_passwd |
68 | +Type: password |
69 | +_Description: Administrator password to join the domain |
70 | + |
71 | +Template: ubiquity/text/login_directory |
72 | +Type: text |
73 | +_Description: |
74 | + Use Active Directory |
75 | + |
76 | +Template: ubiquity/text/login_directory_extra_label |
77 | +Type: text |
78 | +_Description: |
79 | + You'll enter domain and other details in the next step. |
80 | + |
81 | +Template: ubiquity/text/domain_label |
82 | +Type: text |
83 | +_Description: |
84 | + Domain: |
85 | + |
86 | +Template: ubiquity/text/domain_name_error_label |
87 | +Type: text |
88 | +_Description: |
89 | + You must enter a domain name |
90 | + |
91 | +Template: ubiquity/text/directory_testbutton |
92 | +Type: text |
93 | +_Description: |
94 | + Test connection |
95 | + |
96 | +Template: ubiquity/text/domain_user_label |
97 | +Type: text |
98 | +_Description: |
99 | + Domain Administrator: |
100 | + |
101 | +Template: ubiquity/text/domain_user_error_label |
102 | +Type: text |
103 | +_Description: |
104 | + You must enter a user name |
105 | + |
106 | +Template: ubiquity/text/domain_passwd_label |
107 | +Type: text |
108 | +_Description: |
109 | + Password: |
110 | + |
111 | +Template: ubiquity/text/directory_information_title |
112 | +Type: text |
113 | +_Description: Configure Active Directory |
114 | + |
115 | +Template: ubiquity/text/hostname_error |
116 | +Type: text |
117 | +_Description: That name already exists on the network. |
118 | + |
119 | +Template: ubiquity/text/domain_connection_error |
120 | +Type: text |
121 | +_Description: Failed to connect to domain. |
122 | diff --git a/gui/gtk/stepUserInfo.ui b/gui/gtk/stepUserInfo.ui |
123 | index 9d64ed2..1eee3ad 100644 |
124 | --- a/gui/gtk/stepUserInfo.ui |
125 | +++ b/gui/gtk/stepUserInfo.ui |
126 | @@ -1,6 +1,7 @@ |
127 | <?xml version="1.0" encoding="UTF-8"?> |
128 | +<!-- Generated with glade 3.22.2 --> |
129 | <interface> |
130 | - <requires lib="gtk+" version="2.16"/> |
131 | + <requires lib="gtk+" version="3.20"/> |
132 | <object class="GtkBox" id="stepUserInfo"> |
133 | <property name="visible">True</property> |
134 | <property name="can_focus">False</property> |
135 | @@ -19,344 +20,514 @@ |
136 | </packing> |
137 | </child> |
138 | <child> |
139 | - <object class="GtkGrid" id="userinfo_table"> |
140 | + <object class="GtkNotebook" id="userinfo_notebook"> |
141 | <property name="visible">True</property> |
142 | - <property name="can_focus">False</property> |
143 | - <property name="border_width">20</property> |
144 | - <property name="column_spacing">6</property> |
145 | - <property name="row_spacing">6</property> |
146 | - <child> |
147 | - <object class="GtkLabel" id="fullname_label"> |
148 | - <property name="visible">True</property> |
149 | - <property name="can_focus">False</property> |
150 | - <property name="xalign">1</property> |
151 | - <property name="label" translatable="yes">Your name:</property> |
152 | - </object> |
153 | - </child> |
154 | - <child> |
155 | - <object class="GtkLabel" id="username_label"> |
156 | - <property name="visible">True</property> |
157 | - <property name="can_focus">False</property> |
158 | - <property name="xalign">1</property> |
159 | - <property name="label" translatable="yes">Pick a username:</property> |
160 | - <property name="justify">right</property> |
161 | - </object> |
162 | - <packing> |
163 | - <property name="left_attach">0</property> |
164 | - <property name="top_attach">2</property> |
165 | - </packing> |
166 | - </child> |
167 | - <child> |
168 | - <object class="GtkLabel" id="password_label"> |
169 | - <property name="visible">True</property> |
170 | - <property name="can_focus">False</property> |
171 | - <property name="xalign">1</property> |
172 | - <property name="label" translatable="yes">Choose a password:</property> |
173 | - <property name="justify">right</property> |
174 | - </object> |
175 | - <packing> |
176 | - <property name="left_attach">0</property> |
177 | - <property name="top_attach">3</property> |
178 | - </packing> |
179 | - </child> |
180 | - <child> |
181 | - <object class="GtkLabel" id="verified_password_label"> |
182 | - <property name="visible">True</property> |
183 | - <property name="can_focus">False</property> |
184 | - <property name="xalign">1</property> |
185 | - <property name="label" translatable="yes">Confirm your password:</property> |
186 | - <property name="justify">right</property> |
187 | - </object> |
188 | - <packing> |
189 | - <property name="left_attach">0</property> |
190 | - <property name="top_attach">4</property> |
191 | - </packing> |
192 | - </child> |
193 | + <property name="can_focus">True</property> |
194 | + <property name="show_tabs">False</property> |
195 | + <property name="show_border">False</property> |
196 | <child> |
197 | - <object class="GtkBox" id="login_vbox"> |
198 | + <object class="GtkGrid" id="userinfo_table"> |
199 | <property name="visible">True</property> |
200 | <property name="can_focus">False</property> |
201 | - <property name="orientation">vertical</property> |
202 | - <property name="spacing">3</property> |
203 | + <property name="border_width">20</property> |
204 | + <property name="row_spacing">6</property> |
205 | + <property name="column_spacing">6</property> |
206 | <child> |
207 | - <object class="GtkRadioButton" id="login_auto"> |
208 | - <property name="label" translatable="yes">Log in automatically</property> |
209 | + <object class="GtkLabel" id="fullname_label"> |
210 | <property name="visible">True</property> |
211 | - <property name="can_focus">True</property> |
212 | - <property name="receives_default">False</property> |
213 | - <property name="use_action_appearance">False</property> |
214 | - <property name="xalign">0</property> |
215 | - <property name="draw_indicator">True</property> |
216 | - <property name="group">login_pass</property> |
217 | + <property name="can_focus">False</property> |
218 | + <property name="label" translatable="yes">Your name:</property> |
219 | + <property name="xalign">1</property> |
220 | </object> |
221 | <packing> |
222 | - <property name="expand">False</property> |
223 | - <property name="fill">False</property> |
224 | - <property name="position">0</property> |
225 | + <property name="left_attach">0</property> |
226 | + <property name="top_attach">0</property> |
227 | </packing> |
228 | </child> |
229 | <child> |
230 | - <object class="GtkRadioButton" id="login_pass"> |
231 | - <property name="label" translatable="yes">Require my password to log in</property> |
232 | + <object class="GtkLabel" id="username_label"> |
233 | <property name="visible">True</property> |
234 | - <property name="can_focus">True</property> |
235 | - <property name="receives_default">False</property> |
236 | - <property name="use_action_appearance">False</property> |
237 | - <property name="xalign">0</property> |
238 | - <property name="active">True</property> |
239 | - <property name="draw_indicator">True</property> |
240 | + <property name="can_focus">False</property> |
241 | + <property name="label" translatable="yes">Pick a username:</property> |
242 | + <property name="justify">right</property> |
243 | + <property name="xalign">1</property> |
244 | </object> |
245 | <packing> |
246 | - <property name="expand">False</property> |
247 | - <property name="fill">False</property> |
248 | - <property name="position">1</property> |
249 | + <property name="left_attach">0</property> |
250 | + <property name="top_attach">2</property> |
251 | </packing> |
252 | </child> |
253 | - </object> |
254 | - <packing> |
255 | - <property name="left_attach">1</property> |
256 | - <property name="top_attach">5</property> |
257 | - </packing> |
258 | - </child> |
259 | - <child> |
260 | - <object class="GtkBox" id="hbox1"> |
261 | - <property name="visible">True</property> |
262 | - <property name="can_focus">False</property> |
263 | - <property name="spacing">6</property> |
264 | <child> |
265 | - <object class="GtkEntry" id="password"> |
266 | + <object class="GtkLabel" id="password_label"> |
267 | <property name="visible">True</property> |
268 | - <property name="can_focus">True</property> |
269 | - <property name="visibility">False</property> |
270 | - <property name="invisible_char">●</property> |
271 | - <property name="activates_default">True</property> |
272 | - <property name="width_chars">20</property> |
273 | - <property name="invisible_char_set">True</property> |
274 | - <accessibility> |
275 | - <relation type="labelled-by" target="password_label"/> |
276 | - </accessibility> |
277 | - <signal name="changed" handler="info_loop" swapped="no"/> |
278 | + <property name="can_focus">False</property> |
279 | + <property name="label" translatable="yes">Choose a password:</property> |
280 | + <property name="justify">right</property> |
281 | + <property name="xalign">1</property> |
282 | </object> |
283 | <packing> |
284 | - <property name="expand">False</property> |
285 | - <property name="fill">False</property> |
286 | - <property name="position">0</property> |
287 | + <property name="left_attach">0</property> |
288 | + <property name="top_attach">3</property> |
289 | </packing> |
290 | </child> |
291 | <child> |
292 | - <object class="GtkLabel" id="password_strength"> |
293 | + <object class="GtkLabel" id="verified_password_label"> |
294 | + <property name="visible">True</property> |
295 | <property name="can_focus">False</property> |
296 | - <property name="xalign">0</property> |
297 | - <property name="label" translatable="yes"><small><span color="darkgreen">Strong password</span></small></property> |
298 | - <property name="use_markup">True</property> |
299 | + <property name="label" translatable="yes">Confirm your password:</property> |
300 | + <property name="justify">right</property> |
301 | + <property name="xalign">1</property> |
302 | </object> |
303 | <packing> |
304 | - <property name="expand">False</property> |
305 | - <property name="fill">False</property> |
306 | - <property name="position">1</property> |
307 | + <property name="left_attach">0</property> |
308 | + <property name="top_attach">4</property> |
309 | </packing> |
310 | </child> |
311 | - </object> |
312 | - <packing> |
313 | - <property name="left_attach">1</property> |
314 | - <property name="top_attach">3</property> |
315 | - </packing> |
316 | - </child> |
317 | - <child> |
318 | - <object class="GtkBox" id="hbox2"> |
319 | - <property name="visible">True</property> |
320 | - <property name="can_focus">False</property> |
321 | - <property name="spacing">6</property> |
322 | <child> |
323 | - <object class="GtkEntry" id="verified_password"> |
324 | + <object class="GtkBox" id="login_vbox"> |
325 | <property name="visible">True</property> |
326 | - <property name="can_focus">True</property> |
327 | - <property name="visibility">False</property> |
328 | - <property name="invisible_char">●</property> |
329 | - <property name="activates_default">True</property> |
330 | - <property name="width_chars">20</property> |
331 | - <property name="invisible_char_set">True</property> |
332 | - <accessibility> |
333 | - <relation type="labelled-by" target="verified_password_label"/> |
334 | - </accessibility> |
335 | - <signal name="changed" handler="info_loop" swapped="no"/> |
336 | + <property name="can_focus">False</property> |
337 | + <property name="orientation">vertical</property> |
338 | + <property name="spacing">3</property> |
339 | + <child> |
340 | + <object class="GtkRadioButton" id="login_auto"> |
341 | + <property name="label" translatable="yes">Log in automatically</property> |
342 | + <property name="visible">True</property> |
343 | + <property name="can_focus">True</property> |
344 | + <property name="receives_default">False</property> |
345 | + <property name="draw_indicator">True</property> |
346 | + <property name="group">login_pass</property> |
347 | + </object> |
348 | + <packing> |
349 | + <property name="expand">False</property> |
350 | + <property name="fill">False</property> |
351 | + <property name="position">0</property> |
352 | + </packing> |
353 | + </child> |
354 | + <child> |
355 | + <object class="GtkRadioButton" id="login_pass"> |
356 | + <property name="label" translatable="yes">Require my password to log in</property> |
357 | + <property name="visible">True</property> |
358 | + <property name="can_focus">True</property> |
359 | + <property name="receives_default">False</property> |
360 | + <property name="active">True</property> |
361 | + <property name="draw_indicator">True</property> |
362 | + </object> |
363 | + <packing> |
364 | + <property name="expand">False</property> |
365 | + <property name="fill">False</property> |
366 | + <property name="position">1</property> |
367 | + </packing> |
368 | + </child> |
369 | </object> |
370 | <packing> |
371 | - <property name="expand">False</property> |
372 | - <property name="fill">False</property> |
373 | - <property name="position">0</property> |
374 | + <property name="left_attach">1</property> |
375 | + <property name="top_attach">5</property> |
376 | </packing> |
377 | </child> |
378 | <child> |
379 | - <object class="GtkImage" id="password_ok"> |
380 | + <object class="GtkBox" id="hbox1"> |
381 | + <property name="visible">True</property> |
382 | <property name="can_focus">False</property> |
383 | - <property name="stock">gtk-yes</property> |
384 | + <property name="spacing">6</property> |
385 | + <child> |
386 | + <object class="GtkEntry" id="password"> |
387 | + <property name="visible">True</property> |
388 | + <property name="can_focus">True</property> |
389 | + <property name="visibility">False</property> |
390 | + <property name="invisible_char">●</property> |
391 | + <property name="activates_default">True</property> |
392 | + <property name="width_chars">20</property> |
393 | + <signal name="changed" handler="info_loop" swapped="no"/> |
394 | + <accessibility> |
395 | + <relation type="labelled-by" target="password_label"/> |
396 | + </accessibility> |
397 | + </object> |
398 | + <packing> |
399 | + <property name="expand">False</property> |
400 | + <property name="fill">False</property> |
401 | + <property name="position">0</property> |
402 | + </packing> |
403 | + </child> |
404 | + <child> |
405 | + <object class="GtkLabel" id="password_strength"> |
406 | + <property name="can_focus">False</property> |
407 | + <property name="label" translatable="yes"><small><span color="darkgreen">Strong password</span></small></property> |
408 | + <property name="use_markup">True</property> |
409 | + <property name="xalign">0</property> |
410 | + </object> |
411 | + <packing> |
412 | + <property name="expand">False</property> |
413 | + <property name="fill">False</property> |
414 | + <property name="position">1</property> |
415 | + </packing> |
416 | + </child> |
417 | </object> |
418 | <packing> |
419 | - <property name="expand">False</property> |
420 | - <property name="fill">False</property> |
421 | - <property name="position">1</property> |
422 | + <property name="left_attach">1</property> |
423 | + <property name="top_attach">3</property> |
424 | </packing> |
425 | </child> |
426 | <child> |
427 | - <object class="GtkLabel" id="password_error_label"> |
428 | + <object class="GtkBox" id="hbox2"> |
429 | <property name="visible">True</property> |
430 | <property name="can_focus">False</property> |
431 | - <property name="xalign">0</property> |
432 | - <property name="label" translatable="yes"><small><span color="darkred">You must enter a username</span></small></property> |
433 | - <property name="use_markup">True</property> |
434 | + <property name="spacing">6</property> |
435 | + <child> |
436 | + <object class="GtkEntry" id="verified_password"> |
437 | + <property name="visible">True</property> |
438 | + <property name="can_focus">True</property> |
439 | + <property name="visibility">False</property> |
440 | + <property name="invisible_char">●</property> |
441 | + <property name="activates_default">True</property> |
442 | + <property name="width_chars">20</property> |
443 | + <signal name="changed" handler="info_loop" swapped="no"/> |
444 | + <accessibility> |
445 | + <relation type="labelled-by" target="verified_password_label"/> |
446 | + </accessibility> |
447 | + </object> |
448 | + <packing> |
449 | + <property name="expand">False</property> |
450 | + <property name="fill">False</property> |
451 | + <property name="position">0</property> |
452 | + </packing> |
453 | + </child> |
454 | + <child> |
455 | + <object class="GtkImage" id="password_ok"> |
456 | + <property name="can_focus">False</property> |
457 | + <property name="stock">gtk-yes</property> |
458 | + </object> |
459 | + <packing> |
460 | + <property name="expand">False</property> |
461 | + <property name="fill">False</property> |
462 | + <property name="position">1</property> |
463 | + </packing> |
464 | + </child> |
465 | + <child> |
466 | + <object class="GtkLabel" id="password_error_label"> |
467 | + <property name="visible">True</property> |
468 | + <property name="can_focus">False</property> |
469 | + <property name="label" translatable="yes"><small><span color="darkred">You must enter a username</span></small></property> |
470 | + <property name="use_markup">True</property> |
471 | + <property name="xalign">0</property> |
472 | + </object> |
473 | + <packing> |
474 | + <property name="expand">False</property> |
475 | + <property name="fill">False</property> |
476 | + <property name="position">2</property> |
477 | + </packing> |
478 | + </child> |
479 | </object> |
480 | <packing> |
481 | - <property name="expand">False</property> |
482 | - <property name="fill">False</property> |
483 | - <property name="position">2</property> |
484 | + <property name="left_attach">1</property> |
485 | + <property name="top_attach">4</property> |
486 | </packing> |
487 | </child> |
488 | - </object> |
489 | - <packing> |
490 | - <property name="left_attach">1</property> |
491 | - <property name="top_attach">4</property> |
492 | - </packing> |
493 | - </child> |
494 | - <child> |
495 | - <object class="GtkBox" id="hbox3"> |
496 | - <property name="visible">True</property> |
497 | - <property name="can_focus">False</property> |
498 | - <property name="spacing">6</property> |
499 | <child> |
500 | - <object class="GtkEntry" id="fullname"> |
501 | + <object class="GtkBox" id="hbox3"> |
502 | <property name="visible">True</property> |
503 | - <property name="can_focus">True</property> |
504 | - <property name="invisible_char">•</property> |
505 | - <property name="activates_default">True</property> |
506 | - <property name="width_chars">40</property> |
507 | - <accessibility> |
508 | - <relation type="labelled-by" target="fullname_label"/> |
509 | - </accessibility> |
510 | - <signal name="changed" handler="info_loop" swapped="no"/> |
511 | + <property name="can_focus">False</property> |
512 | + <property name="spacing">6</property> |
513 | + <child> |
514 | + <object class="GtkEntry" id="fullname"> |
515 | + <property name="visible">True</property> |
516 | + <property name="can_focus">True</property> |
517 | + <property name="invisible_char">•</property> |
518 | + <property name="activates_default">True</property> |
519 | + <property name="width_chars">40</property> |
520 | + <signal name="changed" handler="info_loop" swapped="no"/> |
521 | + <accessibility> |
522 | + <relation type="labelled-by" target="fullname_label"/> |
523 | + </accessibility> |
524 | + </object> |
525 | + <packing> |
526 | + <property name="expand">False</property> |
527 | + <property name="fill">False</property> |
528 | + <property name="position">0</property> |
529 | + </packing> |
530 | + </child> |
531 | + <child> |
532 | + <object class="GtkImage" id="fullname_ok"> |
533 | + <property name="can_focus">False</property> |
534 | + <property name="stock">gtk-yes</property> |
535 | + </object> |
536 | + <packing> |
537 | + <property name="expand">False</property> |
538 | + <property name="fill">False</property> |
539 | + <property name="position">1</property> |
540 | + </packing> |
541 | + </child> |
542 | </object> |
543 | <packing> |
544 | - <property name="expand">False</property> |
545 | - <property name="fill">False</property> |
546 | - <property name="position">0</property> |
547 | + <property name="left_attach">1</property> |
548 | + <property name="top_attach">0</property> |
549 | </packing> |
550 | </child> |
551 | <child> |
552 | - <object class="GtkImage" id="fullname_ok"> |
553 | + <object class="GtkBox" id="username_box"> |
554 | + <property name="visible">True</property> |
555 | <property name="can_focus">False</property> |
556 | - <property name="stock">gtk-yes</property> |
557 | + <property name="spacing">6</property> |
558 | + <child> |
559 | + <object class="GtkEntry" id="username"> |
560 | + <property name="visible">True</property> |
561 | + <property name="can_focus">True</property> |
562 | + <property name="max_length">32</property> |
563 | + <property name="invisible_char">•</property> |
564 | + <property name="activates_default">True</property> |
565 | + <property name="width_chars">15</property> |
566 | + <signal name="changed" handler="info_loop" swapped="no"/> |
567 | + <accessibility> |
568 | + <relation type="labelled-by" target="username_label"/> |
569 | + </accessibility> |
570 | + </object> |
571 | + <packing> |
572 | + <property name="expand">False</property> |
573 | + <property name="fill">False</property> |
574 | + <property name="position">0</property> |
575 | + </packing> |
576 | + </child> |
577 | + <child> |
578 | + <object class="GtkImage" id="username_ok"> |
579 | + <property name="can_focus">False</property> |
580 | + <property name="stock">gtk-yes</property> |
581 | + </object> |
582 | + <packing> |
583 | + <property name="expand">False</property> |
584 | + <property name="fill">False</property> |
585 | + <property name="position">1</property> |
586 | + </packing> |
587 | + </child> |
588 | + <child> |
589 | + <object class="GtkLabel" id="username_error_label"> |
590 | + <property name="visible">True</property> |
591 | + <property name="can_focus">False</property> |
592 | + <property name="label" translatable="yes"><small><span color="darkred">You must enter a username</span></small></property> |
593 | + <property name="use_markup">True</property> |
594 | + <property name="wrap">True</property> |
595 | + <property name="xalign">0</property> |
596 | + </object> |
597 | + <packing> |
598 | + <property name="expand">False</property> |
599 | + <property name="fill">False</property> |
600 | + <property name="position">2</property> |
601 | + </packing> |
602 | + </child> |
603 | </object> |
604 | <packing> |
605 | - <property name="expand">False</property> |
606 | - <property name="fill">False</property> |
607 | - <property name="position">1</property> |
608 | + <property name="left_attach">1</property> |
609 | + <property name="top_attach">2</property> |
610 | </packing> |
611 | </child> |
612 | - </object> |
613 | - <packing> |
614 | - <property name="left_attach">1</property> |
615 | - </packing> |
616 | - </child> |
617 | - <child> |
618 | - <object class="GtkBox" id="username_box"> |
619 | - <property name="visible">True</property> |
620 | - <property name="can_focus">False</property> |
621 | - <property name="spacing">6</property> |
622 | <child> |
623 | - <object class="GtkEntry" id="username"> |
624 | + <object class="GtkBox" id="box1"> |
625 | <property name="visible">True</property> |
626 | - <property name="can_focus">True</property> |
627 | - <property name="max_length">32</property> |
628 | - <property name="invisible_char">•</property> |
629 | - <property name="activates_default">True</property> |
630 | - <property name="width_chars">15</property> |
631 | - <accessibility> |
632 | - <relation type="labelled-by" target="username_label"/> |
633 | - </accessibility> |
634 | - <signal name="changed" handler="info_loop" swapped="no"/> |
635 | + <property name="can_focus">False</property> |
636 | + <property name="orientation">vertical</property> |
637 | + <child> |
638 | + <placeholder/> |
639 | + </child> |
640 | </object> |
641 | <packing> |
642 | - <property name="expand">False</property> |
643 | - <property name="fill">False</property> |
644 | - <property name="position">0</property> |
645 | + <property name="left_attach">0</property> |
646 | + <property name="top_attach">5</property> |
647 | </packing> |
648 | </child> |
649 | <child> |
650 | - <object class="GtkImage" id="username_ok"> |
651 | + <object class="GtkBox" id="hostname_box"> |
652 | + <property name="visible">True</property> |
653 | <property name="can_focus">False</property> |
654 | - <property name="stock">gtk-yes</property> |
655 | + <property name="orientation">vertical</property> |
656 | + <property name="spacing">3</property> |
657 | + <child> |
658 | + <object class="GtkBox" id="box3"> |
659 | + <property name="visible">True</property> |
660 | + <property name="can_focus">False</property> |
661 | + <property name="spacing">6</property> |
662 | + <child> |
663 | + <object class="GtkEntry" id="hostname"> |
664 | + <property name="visible">True</property> |
665 | + <property name="can_focus">True</property> |
666 | + <property name="invisible_char">•</property> |
667 | + <signal name="changed" handler="info_loop" swapped="no"/> |
668 | + <accessibility> |
669 | + <relation type="labelled-by" target="hostname_label"/> |
670 | + <relation type="labelled-by" target="hostname_extra_label"/> |
671 | + </accessibility> |
672 | + </object> |
673 | + <packing> |
674 | + <property name="expand">False</property> |
675 | + <property name="fill">True</property> |
676 | + <property name="position">0</property> |
677 | + </packing> |
678 | + </child> |
679 | + <child> |
680 | + <object class="GtkImage" id="hostname_ok"> |
681 | + <property name="can_focus">False</property> |
682 | + <property name="stock">gtk-yes</property> |
683 | + </object> |
684 | + <packing> |
685 | + <property name="expand">False</property> |
686 | + <property name="fill">False</property> |
687 | + <property name="position">1</property> |
688 | + </packing> |
689 | + </child> |
690 | + <child> |
691 | + <object class="GtkLabel" id="hostname_error_label"> |
692 | + <property name="visible">True</property> |
693 | + <property name="can_focus">False</property> |
694 | + <property name="label" translatable="yes"><small><span color="darkred">You must enter a name</span></small></property> |
695 | + <property name="use_markup">True</property> |
696 | + <property name="wrap">True</property> |
697 | + </object> |
698 | + <packing> |
699 | + <property name="expand">False</property> |
700 | + <property name="fill">True</property> |
701 | + <property name="position">2</property> |
702 | + </packing> |
703 | + </child> |
704 | + </object> |
705 | + <packing> |
706 | + <property name="expand">False</property> |
707 | + <property name="fill">True</property> |
708 | + <property name="position">0</property> |
709 | + </packing> |
710 | + </child> |
711 | + <child> |
712 | + <object class="GtkLabel" id="hostname_extra_label"> |
713 | + <property name="visible">True</property> |
714 | + <property name="can_focus">False</property> |
715 | + <property name="label" translatable="yes">The name it uses when it talks to other computers.</property> |
716 | + <property name="xalign">0</property> |
717 | + <attributes> |
718 | + <attribute name="scale" value="0.83333333333333304"/> |
719 | + </attributes> |
720 | + </object> |
721 | + <packing> |
722 | + <property name="expand">False</property> |
723 | + <property name="fill">True</property> |
724 | + <property name="position">1</property> |
725 | + </packing> |
726 | + </child> |
727 | </object> |
728 | <packing> |
729 | - <property name="expand">False</property> |
730 | - <property name="fill">False</property> |
731 | - <property name="position">1</property> |
732 | + <property name="left_attach">1</property> |
733 | + <property name="top_attach">1</property> |
734 | </packing> |
735 | </child> |
736 | <child> |
737 | - <object class="GtkLabel" id="username_error_label"> |
738 | + <object class="GtkAlignment" id="alignment2"> |
739 | <property name="visible">True</property> |
740 | <property name="can_focus">False</property> |
741 | - <property name="xalign">0</property> |
742 | - <property name="label" translatable="yes"><small><span color="darkred">You must enter a username</span></small></property> |
743 | - <property name="use_markup">True</property> |
744 | - <property name="wrap">True</property> |
745 | + <property name="bottom_padding">20</property> |
746 | + <child> |
747 | + <object class="GtkLabel" id="hostname_label"> |
748 | + <property name="visible">True</property> |
749 | + <property name="can_focus">False</property> |
750 | + <property name="label" translatable="yes">Your computer's name:</property> |
751 | + <property name="xalign">1</property> |
752 | + </object> |
753 | + </child> |
754 | </object> |
755 | <packing> |
756 | - <property name="expand">False</property> |
757 | - <property name="fill">False</property> |
758 | - <property name="position">2</property> |
759 | + <property name="left_attach">0</property> |
760 | + <property name="top_attach">1</property> |
761 | + </packing> |
762 | + </child> |
763 | + <child> |
764 | + <object class="GtkBox"> |
765 | + <property name="visible">True</property> |
766 | + <property name="can_focus">False</property> |
767 | + <property name="orientation">vertical</property> |
768 | + <property name="spacing">6</property> |
769 | + <child> |
770 | + <object class="GtkCheckButton" id="login_directory"> |
771 | + <property name="label" translatable="yes">Use Active Directory</property> |
772 | + <property name="visible">True</property> |
773 | + <property name="can_focus">True</property> |
774 | + <property name="receives_default">False</property> |
775 | + <property name="draw_indicator">True</property> |
776 | + <signal name="toggled" handler="on_login_directory_toggled" swapped="no"/> |
777 | + </object> |
778 | + <packing> |
779 | + <property name="expand">False</property> |
780 | + <property name="fill">False</property> |
781 | + <property name="position">0</property> |
782 | + </packing> |
783 | + </child> |
784 | + <child> |
785 | + <object class="GtkLabel" id="login_directory_extra_label"> |
786 | + <property name="visible">True</property> |
787 | + <property name="can_focus">False</property> |
788 | + <property name="label" translatable="yes"> You'll enter domain and other details in the next step.</property> |
789 | + <property name="xalign">0</property> |
790 | + <attributes> |
791 | + <attribute name="scale" value="0.83333333333333304"/> |
792 | + </attributes> |
793 | + </object> |
794 | + <packing> |
795 | + <property name="expand">False</property> |
796 | + <property name="fill">True</property> |
797 | + <property name="position">1</property> |
798 | + </packing> |
799 | + </child> |
800 | + </object> |
801 | + <packing> |
802 | + <property name="left_attach">1</property> |
803 | + <property name="top_attach">6</property> |
804 | </packing> |
805 | </child> |
806 | - </object> |
807 | - <packing> |
808 | - <property name="left_attach">1</property> |
809 | - <property name="top_attach">2</property> |
810 | - </packing> |
811 | - </child> |
812 | - <child> |
813 | - <object class="GtkBox" id="box1"> |
814 | - <property name="visible">True</property> |
815 | - <property name="can_focus">False</property> |
816 | - <property name="orientation">vertical</property> |
817 | <child> |
818 | <placeholder/> |
819 | </child> |
820 | </object> |
821 | - <packing> |
822 | - <property name="left_attach">0</property> |
823 | - <property name="top_attach">5</property> |
824 | - </packing> |
825 | + </child> |
826 | + <child type="tab"> |
827 | + <placeholder/> |
828 | </child> |
829 | <child> |
830 | - <object class="GtkBox" id="hostname_box"> |
831 | + <object class="GtkGrid" id="directory_table"> |
832 | <property name="visible">True</property> |
833 | <property name="can_focus">False</property> |
834 | - <property name="orientation">vertical</property> |
835 | - <property name="spacing">3</property> |
836 | + <property name="border_width">20</property> |
837 | + <property name="row_spacing">6</property> |
838 | + <property name="column_spacing">6</property> |
839 | <child> |
840 | - <object class="GtkBox" id="box3"> |
841 | + <object class="GtkLabel" id="domain_user_label"> |
842 | + <property name="visible">True</property> |
843 | + <property name="can_focus">False</property> |
844 | + <property name="label" translatable="yes">Domain administrator:</property> |
845 | + <property name="justify">right</property> |
846 | + <property name="xalign">1</property> |
847 | + </object> |
848 | + <packing> |
849 | + <property name="left_attach">0</property> |
850 | + <property name="top_attach">1</property> |
851 | + </packing> |
852 | + </child> |
853 | + <child> |
854 | + <object class="GtkBox" id="domain_user_box"> |
855 | <property name="visible">True</property> |
856 | <property name="can_focus">False</property> |
857 | <property name="spacing">6</property> |
858 | <child> |
859 | - <object class="GtkEntry" id="hostname"> |
860 | + <object class="GtkEntry" id="domain_user"> |
861 | <property name="visible">True</property> |
862 | <property name="can_focus">True</property> |
863 | + <property name="max_length">32</property> |
864 | <property name="invisible_char">•</property> |
865 | - <accessibility> |
866 | - <relation type="labelled-by" target="hostname_label"/> |
867 | - <relation type="labelled-by" target="hostname_extra_label"/> |
868 | - </accessibility> |
869 | - <signal name="changed" handler="info_loop" swapped="no"/> |
870 | + <property name="activates_default">True</property> |
871 | + <property name="width_chars">15</property> |
872 | + <signal name="changed" handler="validate_directory_info" swapped="no"/> |
873 | </object> |
874 | <packing> |
875 | <property name="expand">False</property> |
876 | - <property name="fill">True</property> |
877 | + <property name="fill">False</property> |
878 | <property name="position">0</property> |
879 | </packing> |
880 | </child> |
881 | <child> |
882 | - <object class="GtkImage" id="hostname_ok"> |
883 | + <object class="GtkImage" id="domain_user_ok"> |
884 | <property name="can_focus">False</property> |
885 | <property name="stock">gtk-yes</property> |
886 | </object> |
887 | @@ -367,71 +538,163 @@ |
888 | </packing> |
889 | </child> |
890 | <child> |
891 | - <object class="GtkLabel" id="hostname_error_label"> |
892 | + <object class="GtkLabel" id="domain_user_error_label"> |
893 | <property name="visible">True</property> |
894 | <property name="can_focus">False</property> |
895 | - <property name="label" translatable="yes"><small><span color="darkred">You must enter a name</span></small></property> |
896 | + <property name="label" translatable="yes"><small><span color="darkred">You must enter a user name</span></small></property> |
897 | <property name="use_markup">True</property> |
898 | <property name="wrap">True</property> |
899 | + <property name="xalign">0</property> |
900 | </object> |
901 | <packing> |
902 | <property name="expand">False</property> |
903 | - <property name="fill">True</property> |
904 | + <property name="fill">False</property> |
905 | <property name="position">2</property> |
906 | </packing> |
907 | </child> |
908 | </object> |
909 | <packing> |
910 | - <property name="expand">False</property> |
911 | - <property name="fill">True</property> |
912 | - <property name="position">0</property> |
913 | + <property name="left_attach">1</property> |
914 | + <property name="top_attach">1</property> |
915 | </packing> |
916 | </child> |
917 | <child> |
918 | - <object class="GtkLabel" id="hostname_extra_label"> |
919 | + <object class="GtkLabel" id="domain_passwd_label"> |
920 | <property name="visible">True</property> |
921 | <property name="can_focus">False</property> |
922 | - <property name="xalign">0</property> |
923 | - <property name="label" translatable="yes">The name it uses when it talks to other computers.</property> |
924 | - <attributes> |
925 | - <attribute name="scale" value="0.83333333333333304"/> |
926 | - </attributes> |
927 | + <property name="label" translatable="yes">Password:</property> |
928 | + <property name="justify">right</property> |
929 | + <property name="xalign">1</property> |
930 | </object> |
931 | <packing> |
932 | - <property name="expand">False</property> |
933 | - <property name="fill">True</property> |
934 | - <property name="position">1</property> |
935 | + <property name="left_attach">0</property> |
936 | + <property name="top_attach">2</property> |
937 | </packing> |
938 | </child> |
939 | - </object> |
940 | - <packing> |
941 | - <property name="left_attach">1</property> |
942 | - <property name="top_attach">1</property> |
943 | - </packing> |
944 | - </child> |
945 | - <child> |
946 | - <object class="GtkAlignment" id="alignment2"> |
947 | - <property name="visible">True</property> |
948 | - <property name="can_focus">False</property> |
949 | - <property name="bottom_padding">20</property> |
950 | <child> |
951 | - <object class="GtkLabel" id="hostname_label"> |
952 | + <object class="GtkBox" id="di_hbox"> |
953 | <property name="visible">True</property> |
954 | <property name="can_focus">False</property> |
955 | + <property name="spacing">6</property> |
956 | + <child> |
957 | + <object class="GtkEntry" id="domain_passwd"> |
958 | + <property name="visible">True</property> |
959 | + <property name="can_focus">True</property> |
960 | + <property name="visibility">False</property> |
961 | + <property name="invisible_char">●</property> |
962 | + <property name="activates_default">True</property> |
963 | + <property name="width_chars">20</property> |
964 | + <signal name="changed" handler="validate_directory_info" swapped="no"/> |
965 | + </object> |
966 | + <packing> |
967 | + <property name="expand">False</property> |
968 | + <property name="fill">False</property> |
969 | + <property name="position">0</property> |
970 | + </packing> |
971 | + </child> |
972 | + <child> |
973 | + <placeholder/> |
974 | + </child> |
975 | + </object> |
976 | + <packing> |
977 | + <property name="left_attach">1</property> |
978 | + <property name="top_attach">2</property> |
979 | + </packing> |
980 | + </child> |
981 | + <child> |
982 | + <object class="GtkLabel" id="domain_label"> |
983 | + <property name="visible">True</property> |
984 | + <property name="can_focus">False</property> |
985 | + <property name="label" translatable="yes">Domain:</property> |
986 | <property name="xalign">1</property> |
987 | - <property name="label" translatable="yes">Your computer's name:</property> |
988 | </object> |
989 | + <packing> |
990 | + <property name="left_attach">0</property> |
991 | + <property name="top_attach">0</property> |
992 | + </packing> |
993 | + </child> |
994 | + <child> |
995 | + <object class="GtkBox" id="di_box"> |
996 | + <property name="visible">True</property> |
997 | + <property name="can_focus">False</property> |
998 | + <property name="spacing">6</property> |
999 | + <child> |
1000 | + <object class="GtkEntry" id="domain_name"> |
1001 | + <property name="visible">True</property> |
1002 | + <property name="can_focus">True</property> |
1003 | + <property name="invisible_char">•</property> |
1004 | + <signal name="changed" handler="validate_directory_info" swapped="no"/> |
1005 | + </object> |
1006 | + <packing> |
1007 | + <property name="expand">False</property> |
1008 | + <property name="fill">True</property> |
1009 | + <property name="position">0</property> |
1010 | + </packing> |
1011 | + </child> |
1012 | + <child> |
1013 | + <object class="GtkButton" id="directory_testbutton"> |
1014 | + <property name="label" translatable="yes">Test connection</property> |
1015 | + <property name="visible">True</property> |
1016 | + <property name="sensitive">False</property> |
1017 | + <property name="can_focus">True</property> |
1018 | + <property name="receives_default">True</property> |
1019 | + <signal name="clicked" handler="on_testdomain_click" swapped="no"/> |
1020 | + </object> |
1021 | + <packing> |
1022 | + <property name="expand">False</property> |
1023 | + <property name="fill">True</property> |
1024 | + <property name="position">1</property> |
1025 | + </packing> |
1026 | + </child> |
1027 | + <child> |
1028 | + <object class="GtkImage" id="domain_name_ok"> |
1029 | + <property name="can_focus">False</property> |
1030 | + <property name="stock">gtk-yes</property> |
1031 | + </object> |
1032 | + <packing> |
1033 | + <property name="expand">False</property> |
1034 | + <property name="fill">False</property> |
1035 | + <property name="position">2</property> |
1036 | + </packing> |
1037 | + </child> |
1038 | + <child> |
1039 | + <object class="GtkLabel" id="domain_name_error_label"> |
1040 | + <property name="visible">True</property> |
1041 | + <property name="can_focus">False</property> |
1042 | + <property name="label" translatable="yes"><small><span color="darkred">You must enter a domain name</span></small></property> |
1043 | + <property name="use_markup">True</property> |
1044 | + <property name="wrap">True</property> |
1045 | + </object> |
1046 | + <packing> |
1047 | + <property name="expand">False</property> |
1048 | + <property name="fill">True</property> |
1049 | + <property name="position">3</property> |
1050 | + </packing> |
1051 | + </child> |
1052 | + </object> |
1053 | + <packing> |
1054 | + <property name="left_attach">1</property> |
1055 | + <property name="top_attach">0</property> |
1056 | + </packing> |
1057 | </child> |
1058 | </object> |
1059 | <packing> |
1060 | - <property name="left_attach">0</property> |
1061 | - <property name="top_attach">1</property> |
1062 | + <property name="position">1</property> |
1063 | </packing> |
1064 | </child> |
1065 | + <child type="tab"> |
1066 | + <placeholder/> |
1067 | + </child> |
1068 | + <child> |
1069 | + <placeholder/> |
1070 | + </child> |
1071 | + <child type="tab"> |
1072 | + <placeholder/> |
1073 | + </child> |
1074 | </object> |
1075 | <packing> |
1076 | <property name="expand">False</property> |
1077 | - <property name="fill">False</property> |
1078 | + <property name="fill">True</property> |
1079 | <property name="position">1</property> |
1080 | </packing> |
1081 | </child> |
1082 | diff --git a/scripts/plugininstall.py b/scripts/plugininstall.py |
1083 | index e9acdc9..434fd3b 100755 |
1084 | --- a/scripts/plugininstall.py |
1085 | +++ b/scripts/plugininstall.py |
1086 | @@ -228,6 +228,10 @@ class Install(install_misc.InstallBase): |
1087 | self.configure_zsys() |
1088 | |
1089 | self.next_region() |
1090 | + self.db.progress('INFO', 'ubiquity/install/activedirectory') |
1091 | + self.configure_active_directory() |
1092 | + |
1093 | + self.next_region() |
1094 | self.db.progress('INFO', 'ubiquity/install/bootloader') |
1095 | self.copy_mok() |
1096 | self.configure_bootloader() |
1097 | @@ -968,6 +972,72 @@ class Install(install_misc.InstallBase): |
1098 | if use_zfs: |
1099 | misc.execute_root('/usr/share/ubiquity/zsys-setup', 'finalize') |
1100 | |
1101 | + def configure_active_directory(self): |
1102 | + """ Join Active Directory domain and enable pam_mkhomedir """ |
1103 | + use_directory = self.db.get('ubiquity/login_use_directory') |
1104 | + if use_directory != 'true': |
1105 | + return |
1106 | + |
1107 | + from socket import gethostname |
1108 | + hostname_cur = gethostname() |
1109 | + hostname_new = '' |
1110 | + with open(self.target_file('etc/hostname'), 'r') as f: |
1111 | + hostname_new = f.read().strip() |
1112 | + |
1113 | + # Set hostname for AD to determine FQDN (no fqdn option in realm join, only adcli) |
1114 | + misc.execute_root('hostname', hostname_new) |
1115 | + |
1116 | + directory_domain = self.db.get('ubiquity/directory_domain') |
1117 | + directory_user = self.db.get('ubiquity/directory_user') |
1118 | + directory_passwd = self.db.get('ubiquity/directory_passwd') |
1119 | + |
1120 | + binds = ("/proc", "/sys", "/dev", "/run") |
1121 | + try: |
1122 | + for bind in binds: |
1123 | + misc.execute('mount', '--bind', bind, self.target + bind) |
1124 | + # join AD on host (services are running on host) |
1125 | + if not self.join_domain(hostname_new, directory_domain, directory_user, directory_passwd): |
1126 | + self.db.input('critical', 'ubiquity/install/broken_active_directory') |
1127 | + self.db.go() |
1128 | + finally: |
1129 | + for bind in binds: |
1130 | + misc.execute('umount', '-f', self.target + bind) |
1131 | + # Reset hostname |
1132 | + misc.execute_root('hostname', hostname_cur) |
1133 | + |
1134 | + # Enable pam_mkhomedir |
1135 | + try: |
1136 | + subprocess.check_call(['chroot', self.target, 'pam-auth-update', |
1137 | + '--package', '--enable', 'mkhomedir'], |
1138 | + preexec_fn=install_misc.debconf_disconnect) |
1139 | + except subprocess.CalledProcessError: |
1140 | + self.db.input('critical', 'ubiquity/install/broken_active_directory') |
1141 | + self.db.go() |
1142 | + |
1143 | + def join_domain(self, hostname, directory_domain, directory_user, directory_passwd): |
1144 | + """ Join an Active Directory domain """ |
1145 | + log_args = ['log-output', '-t', 'ubiquity'] |
1146 | + log_args.extend(['realm', 'join', '--install', self.target, |
1147 | + '--user', directory_user, '--computer-name', hostname, |
1148 | + '--unattended', directory_domain]) |
1149 | + try: |
1150 | + p = subprocess.run(log_args, input=directory_passwd, timeout=60, encoding="utf-8") |
1151 | + except TimeoutError as e: |
1152 | + syslog.syslog(syslog.LOG_ERR, ' '.join(log_args)) |
1153 | + syslog.syslog(syslog.LOG_ERR, "Command timed out(%s): %s" % (e.errno, e.strerror)) |
1154 | + return False |
1155 | + except IOError as e: |
1156 | + syslog.syslog(syslog.LOG_ERR, ' '.join(log_args)) |
1157 | + syslog.syslog(syslog.LOG_ERR, "OS error(%s): %s" % (e.errno, e.strerror)) |
1158 | + return False |
1159 | + |
1160 | + if p.returncode != 0: |
1161 | + syslog.syslog(syslog.LOG_ERR, ' '.join(log_args)) |
1162 | + return False |
1163 | + |
1164 | + syslog.syslog(' '.join(log_args)) |
1165 | + return True |
1166 | + |
1167 | def copy_mok(self): |
1168 | if 'UBIQUITY_OEM_USER_CONFIG' in os.environ: |
1169 | return |
1170 | diff --git a/tests/test_usersetup.py b/tests/test_usersetup.py |
1171 | index 0d6c178..33f4949 100644 |
1172 | --- a/tests/test_usersetup.py |
1173 | +++ b/tests/test_usersetup.py |
1174 | @@ -41,6 +41,7 @@ class UserSetupTests(unittest.TestCase): |
1175 | error_msg = 'That name already exists on the network.' |
1176 | self.gtk.resolver = UbiquityMockResolver.MockResolver( |
1177 | hostname='myhostname') |
1178 | + self.gtk.plugin_translate('en') |
1179 | self.gtk.hostname_ok.show() |
1180 | self.gtk.hostname.set_text('myhostname') |
1181 | self.gtk.hostname_error = mock.Mock() |
1182 | diff --git a/ubiquity/components/plugininstall.py b/ubiquity/components/plugininstall.py |
1183 | index 213b57e..dcb04d6 100644 |
1184 | --- a/ubiquity/components/plugininstall.py |
1185 | +++ b/ubiquity/components/plugininstall.py |
1186 | @@ -65,6 +65,8 @@ class Install(FilteredCommand): |
1187 | return True |
1188 | elif question == 'apt-setup/security-updates-failed': |
1189 | fatal = False |
1190 | + elif question == 'ubiquity/install/broken_active_directory': |
1191 | + fatal = False |
1192 | else: |
1193 | fatal = True |
1194 | self.frontend.error_dialog(self.description(question), |
1195 | diff --git a/ubiquity/frontend/gtk_ui.py b/ubiquity/frontend/gtk_ui.py |
1196 | index 7280f96..c3a7dea 100644 |
1197 | --- a/ubiquity/frontend/gtk_ui.py |
1198 | +++ b/ubiquity/frontend/gtk_ui.py |
1199 | @@ -1887,14 +1887,22 @@ class Wizard(BaseFrontend): |
1200 | msg = title |
1201 | dialog = Gtk.MessageDialog( |
1202 | self.live_installer, Gtk.DialogFlags.MODAL, |
1203 | - Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, msg) |
1204 | + Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "") |
1205 | dialog.set_title(title) |
1206 | + dialog.set_markup(msg) |
1207 | + for label in dialog.get_message_area().get_children(): |
1208 | + if not isinstance(label, Gtk.Label): |
1209 | + continue |
1210 | + label.connect('activate-link', self.on_link_clicked) |
1211 | dialog.run() |
1212 | self.set_busy_cursor(saved_busy_cursor) |
1213 | dialog.hide() |
1214 | if fatal: |
1215 | self.return_to_partitioning() |
1216 | |
1217 | + def on_link_clicked(self, widget, uri): |
1218 | + misc.launch_uri(uri) |
1219 | + |
1220 | def toggle_grub_fail(self, unused_widget): |
1221 | if self.grub_no_new_device.get_active(): |
1222 | self.no_grub_warn.show() |
1223 | diff --git a/ubiquity/plugins/ubi-usersetup.py b/ubiquity/plugins/ubi-usersetup.py |
1224 | index 57f2a35..b61d74a 100644 |
1225 | --- a/ubiquity/plugins/ubi-usersetup.py |
1226 | +++ b/ubiquity/plugins/ubi-usersetup.py |
1227 | @@ -31,7 +31,7 @@ import re |
1228 | |
1229 | import debconf |
1230 | |
1231 | -from ubiquity import misc, plugin, validation |
1232 | +from ubiquity import i18n, misc, plugin, validation |
1233 | |
1234 | |
1235 | NAME = 'usersetup' |
1236 | @@ -146,6 +146,10 @@ class PageBase(plugin.PluginUI): |
1237 | def set_allow_password_empty(self, empty): |
1238 | self.allow_password_empty = empty |
1239 | |
1240 | + def plugin_translate(self, lang): |
1241 | + self.hostname_error_text = i18n.get_string('hostname_error', lang) |
1242 | + self.domain_connection_error_text = i18n.get_string('domain_connection_error', lang) |
1243 | + |
1244 | |
1245 | class PageGtk(PageBase): |
1246 | plugin_title = 'ubiquity/text/userinfo_heading_label' |
1247 | @@ -186,6 +190,19 @@ class PageGtk(PageBase): |
1248 | self.password_ok = builder.get_object('password_ok') |
1249 | self.password_strength = builder.get_object('password_strength') |
1250 | |
1251 | + self.login_directory = builder.get_object('login_directory') |
1252 | + self.login_directory_extra_label = builder.get_object('login_directory_extra_label') |
1253 | + self.domain_name = builder.get_object('domain_name') |
1254 | + self.domain_name_ok = builder.get_object('domain_name_ok') |
1255 | + self.domain_name_error_label = builder.get_object('domain_name_error_label') |
1256 | + self.domain_user = builder.get_object('domain_user') |
1257 | + self.domain_user_ok = builder.get_object('domain_user_ok') |
1258 | + self.domain_user_error_label = builder.get_object('domain_user_error_label') |
1259 | + self.domain_passwd = builder.get_object('domain_passwd') |
1260 | + self.directory_testbutton = builder.get_object('directory_testbutton') |
1261 | + |
1262 | + self.userinfo_notebook = builder.get_object('userinfo_notebook') |
1263 | + |
1264 | # Dodgy hack to let us center the contents of the page without it |
1265 | # moving as elements appear and disappear, specifically the full name |
1266 | # okay check icon and the hostname error messages. |
1267 | @@ -204,6 +221,11 @@ class PageGtk(PageBase): |
1268 | self.hostname_changed_id = self.hostname.connect( |
1269 | 'changed', self.on_hostname_changed) |
1270 | |
1271 | + if not os.path.exists('/usr/sbin/realm'): |
1272 | + self.login_directory.hide() |
1273 | + self.login_directory_extra_label.hide() |
1274 | + self.login_directory_extra_label.set_sensitive(False) |
1275 | + |
1276 | if self.controller.oem_config: |
1277 | self.fullname.set_text('OEM Configuration (temporary user)') |
1278 | self.fullname.set_editable(False) |
1279 | @@ -272,11 +294,41 @@ class PageGtk(PageBase): |
1280 | def set_hostname(self, value): |
1281 | self.hostname.set_text(value) |
1282 | |
1283 | + def get_login_directory(self): |
1284 | + """ Use a directory for authentication """ |
1285 | + return self.login_directory.get_active() |
1286 | + |
1287 | + def get_domain_name(self): |
1288 | + """ Get the domain name """ |
1289 | + return self.domain_name.get_text() |
1290 | + |
1291 | + def get_domain_user(self): |
1292 | + """ Get the domain name """ |
1293 | + return self.domain_user.get_text() |
1294 | + |
1295 | + def get_domain_passwd(self): |
1296 | + """ Get the domain name """ |
1297 | + return self.domain_passwd.get_text() |
1298 | + |
1299 | + def domain_name_error(self, msg): |
1300 | + self.domain_name_ok.hide() |
1301 | + m = '<small><span foreground="darkred"><b>%s</b></span></small>' % msg |
1302 | + self.domain_name_error_label.set_markup(m) |
1303 | + self.domain_name_error_label.show() |
1304 | + |
1305 | + def domain_user_error(self, msg): |
1306 | + self.domain_user_ok.hide() |
1307 | + m = '<small><span foreground="darkred"><b>%s</b></span></small>' % msg |
1308 | + self.domain_user_error_label.set_markup(m) |
1309 | + self.domain_user_error_label.show() |
1310 | + |
1311 | def clear_errors(self): |
1312 | self.username_error_label.hide() |
1313 | self.hostname_error_label.hide() |
1314 | self.password_error_label.hide() |
1315 | |
1316 | + self.domain_name_error_label.hide() |
1317 | + |
1318 | # Callback functions. |
1319 | |
1320 | def info_loop(self, widget): |
1321 | @@ -380,8 +432,7 @@ class PageGtk(PageBase): |
1322 | except GLib.GError: |
1323 | pass |
1324 | else: |
1325 | - # FIXME: i18n |
1326 | - self.hostname_error('That name already exists on the network.') |
1327 | + self.hostname_error(self.hostname_error_text) |
1328 | self.hostname_ok.hide() |
1329 | |
1330 | def hostname_timeout(self, widget): |
1331 | @@ -407,6 +458,91 @@ class PageGtk(PageBase): |
1332 | else: |
1333 | self.resolver_ok = False |
1334 | |
1335 | + def validate_directory_info(self, widget=None): |
1336 | + """ Validate domain information """ |
1337 | + domain_name_is_valid = True |
1338 | + domain_info_complete = True |
1339 | + |
1340 | + domain_name_txt = self.domain_name.get_text().strip() |
1341 | + domain_user_txt = self.domain_user.get_text() |
1342 | + domain_passwd_txt = self.domain_passwd.get_text() |
1343 | + |
1344 | + self.domain_name_ok.hide() |
1345 | + if domain_name_txt: |
1346 | + errors = check_hostname(domain_name_txt) |
1347 | + if errors: |
1348 | + self.domain_name_error(make_error_string(self.controller, errors)) |
1349 | + domain_name_is_valid = False |
1350 | + else: |
1351 | + self.domain_name_error_label.hide() |
1352 | + else: |
1353 | + self.domain_name_error_label.hide() |
1354 | + domain_name_is_valid = False |
1355 | + self.directory_testbutton.set_sensitive(domain_name_is_valid) |
1356 | + domain_info_complete = domain_name_is_valid |
1357 | + |
1358 | + if domain_user_txt: |
1359 | + # Don't enforce lower case for AD administrator. |
1360 | + errors = check_username(domain_user_txt.lower()) |
1361 | + if errors: |
1362 | + self.domain_user_error(make_error_string(self.controller, errors)) |
1363 | + domain_info_complete = False |
1364 | + else: |
1365 | + self.domain_user_ok.show() |
1366 | + self.domain_user_error_label.hide() |
1367 | + else: |
1368 | + self.domain_user_ok.hide() |
1369 | + self.domain_user_error_label.hide() |
1370 | + domain_info_complete = False |
1371 | + |
1372 | + if not domain_passwd_txt: |
1373 | + domain_info_complete = False |
1374 | + |
1375 | + self.controller.allow_go_forward(domain_info_complete) |
1376 | + |
1377 | + def switch_userinfo_tab(self, tab): |
1378 | + self.userinfo_notebook.set_current_page(tab) |
1379 | + |
1380 | + if tab == 1: |
1381 | + self.title = 'ubiquity/text/directory_information_title' |
1382 | + self.controller.allow_go_backward(True) |
1383 | + self.validate_directory_info() |
1384 | + else: |
1385 | + self.title = self.plugin_title |
1386 | + self.controller.allow_go_backward(False) |
1387 | + self.controller.allow_go_forward(True) |
1388 | + |
1389 | + self.controller._wizard.set_page_title(self) |
1390 | + |
1391 | + def plugin_set_online_state(self, state): |
1392 | + if not state: |
1393 | + self.login_directory.set_active(False) |
1394 | + self.login_directory.set_sensitive(state) |
1395 | + |
1396 | + def plugin_on_next_clicked(self): |
1397 | + if self.userinfo_notebook.get_current_page() == 0 and self.get_login_directory(): |
1398 | + self.switch_userinfo_tab(1) |
1399 | + return True |
1400 | + return False |
1401 | + |
1402 | + def plugin_on_back_clicked(self): |
1403 | + if self.userinfo_notebook.get_current_page() == 1: |
1404 | + self.switch_userinfo_tab(0) |
1405 | + return True |
1406 | + return False |
1407 | + |
1408 | + def on_testdomain_click(self, widget): |
1409 | + if misc.execute('realm', 'discover', self.domain_name.get_text()): |
1410 | + self.domain_name_ok.show() |
1411 | + self.domain_name_error_label.hide() |
1412 | + else: |
1413 | + self.domain_name_ok.hide() |
1414 | + self.domain_name_error(self.domain_connection_error_text) |
1415 | + self.domain_name_error_label.show() |
1416 | + |
1417 | + def on_login_directory_toggled(self, widget): |
1418 | + self.login_directory_extra_label.set_sensitive(widget.get_active()) |
1419 | + |
1420 | |
1421 | class PageKde(PageBase): |
1422 | plugin_breadcrumb = 'ubiquity/text/breadcrumb_user' |
1423 | @@ -746,6 +882,13 @@ class Page(plugin.Plugin): |
1424 | else: |
1425 | self.preseed('netcfg/get_domain', '') |
1426 | |
1427 | + if hasattr(self.ui, 'get_login_directory'): |
1428 | + self.preseed_bool('ubiquity/login_use_directory', self.ui.get_login_directory()) |
1429 | + if self.ui.get_login_directory(): |
1430 | + self.preseed('ubiquity/directory_domain', self.ui.get_domain_name()) |
1431 | + self.preseed('ubiquity/directory_user', self.ui.get_domain_user()) |
1432 | + self.preseed('ubiquity/directory_passwd', self.ui.get_domain_passwd()) |
1433 | + |
1434 | plugin.Plugin.ok_handler(self) |
1435 | |
1436 | def error(self, priority, question): |
Cheers. Looks mostly good code-wise, just a few small-ish comments/questions down there.
I'm going to also request a 'design' review from Matthew. (I guess that for this it would be appreciated if you could upload .debs somewhere maybe...)