Merge ~jibel/ubiquity:active_directory into ubiquity:master

Proposed by Jean-Baptiste Lallement
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)
Reviewer Review Type Date Requested Status
Matthew Paul Thomas (community) design Needs Fixing
Iain Lane Approve
Review via email: mp+390221@code.launchpad.net

Commit message

Support for Active directory to the GTK UI.

To post a comment you must log in.
Revision history for this message
Iain Lane (laney) wrote :

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...)

review: Needs Fixing
Revision history for this message
Jean-Baptiste Lallement (jibel) wrote :

@Laney, thanks for the review.

Here is the design review https://docs.google.com/document/d/1_KEGJa2-ka1oNCzMvLlQg9rNW9JESzHAcgqrjP3DkW4/edit?ts=5f561950#

The comments from mpt have all been addressed.

Revision history for this message
Jean-Baptiste Lallement (jibel) :
Revision history for this message
Jean-Baptiste Lallement (jibel) wrote :

Branch as been updated.

Revision history for this message
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.

review: Approve
Revision history for this message
Iain Lane (laney) wrote :

I saw this got merged without the two things I requested, but I would still appreciate them happening.

Revision history for this message
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.com/activedirectory to fix it after installation: Done, but the URL was formatted as a link (perhaps misled by Google Docs auto-linking the URL in my comment). If it’s not actually possible to fix it before installation finishes, people shouldn’t visit the page during installation, so making it a link would be misleading. Also, remember to submit a request for the Web team to set up that URL as a redirect.

review: Needs Fixing (design)
Revision history for this message
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.

Revision history for this message
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.

Revision history for this message
Jean-Baptiste Lallement (jibel) wrote :
Revision history for this message
Jean-Baptiste Lallement (jibel) wrote :

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/debian/changelog b/debian/changelog
index 286dc17..739798c 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,11 @@
1ubiquity (20.10.10) UNRELEASED; urgency=medium
2
3 [ Didier Roche ]
4 [ Jean-Baptiste Lallement ]
5 * AD integration for GTK UI.
6
7 -- Jean-Baptiste Lallement <jean-baptiste.lallement@ubuntu.com> Tue, 25 Aug 2020 10:06:29 +0200
8
1ubiquity (20.10.9) groovy; urgency=medium9ubiquity (20.10.9) groovy; urgency=medium
210
3 * gtk_ui, prepare: Run 'apt update' before installing OEM metapackages. We11 * gtk_ui, prepare: Run 'apt update' before installing OEM metapackages. We
diff --git a/debian/ubiquity.templates b/debian/ubiquity.templates
index 89a32e1..eb6d724 100644
--- a/debian/ubiquity.templates
+++ b/debian/ubiquity.templates
@@ -656,6 +656,10 @@ Template: ubiquity/install/bootloader
656Type: text656Type: text
657_Description: Configuring boot loader...657_Description: Configuring boot loader...
658658
659Template: ubiquity/install/activedirectory
660Type: text
661_Description: Configuring Active Directory...
662
659Template: ubiquity/install/apt_clone_save663Template: ubiquity/install/apt_clone_save
660Type: text664Type: text
661_Description: Saving installed packages...665_Description: Saving installed packages...
@@ -770,6 +774,14 @@ _Description: Error restoring installed applications
770 installation will continue, but you may have to manually reinstall some774 installation will continue, but you may have to manually reinstall some
771 applications after the computer reboots.775 applications after the computer reboots.
772776
777Template: ubiquity/install/broken_active_directory
778Type: error
779_Description: Error configuring connection to Active Directory
780 Sorry, Active Directory can't be set up at the moment. Once your system is up
781 and running, visit
782 <a href="https://discourse.ubuntu.com/t/service-sssd/11579">ubuntu.com/activedirectory</a>
783 for help.
784
773Template: ubiquity/install/md5_check785Template: ubiquity/install/md5_check
774Type: boolean786Type: boolean
775Default: true787Default: true
@@ -1637,4 +1649,72 @@ _Description:
16371649
1638Template: ubiquity/zfs_keystore_key1650Template: ubiquity/zfs_keystore_key
1639Type: password1651Type: password
1640_Description: Key to secure the keystore on ZFS installations
1641\ No newline at end of file1652\ No newline at end of file
1653_Description: Key to secure the keystore on ZFS installations
1654
1655Template: ubiquity/login_use_directory
1656Type: text
1657_Description: Authenticate against a directory
1658
1659Template: ubiquity/directory_domain
1660Type: text
1661_Description: Active Directory domain name
1662
1663Template: ubiquity/directory_user
1664Type: text
1665_Description: Administrator to join the domain
1666
1667Template: ubiquity/directory_passwd
1668Type: password
1669_Description: Administrator password to join the domain
1670
1671Template: ubiquity/text/login_directory
1672Type: text
1673_Description:
1674 Use Active Directory
1675
1676Template: ubiquity/text/login_directory_extra_label
1677Type: text
1678_Description:
1679 You'll enter domain and other details in the next step.
1680
1681Template: ubiquity/text/domain_label
1682Type: text
1683_Description:
1684 Domain:
1685
1686Template: ubiquity/text/domain_name_error_label
1687Type: text
1688_Description:
1689 You must enter a domain name
1690
1691Template: ubiquity/text/directory_testbutton
1692Type: text
1693_Description:
1694 Test connection
1695
1696Template: ubiquity/text/domain_user_label
1697Type: text
1698_Description:
1699 Domain Administrator:
1700
1701Template: ubiquity/text/domain_user_error_label
1702Type: text
1703_Description:
1704 You must enter a user name
1705
1706Template: ubiquity/text/domain_passwd_label
1707Type: text
1708_Description:
1709 Password:
1710
1711Template: ubiquity/text/directory_information_title
1712Type: text
1713_Description: Configure Active Directory
1714
1715Template: ubiquity/text/hostname_error
1716Type: text
1717_Description: That name already exists on the network.
1718
1719Template: ubiquity/text/domain_connection_error
1720Type: text
1721_Description: Failed to connect to domain.
diff --git a/gui/gtk/stepUserInfo.ui b/gui/gtk/stepUserInfo.ui
index 9d64ed2..1eee3ad 100644
--- a/gui/gtk/stepUserInfo.ui
+++ b/gui/gtk/stepUserInfo.ui
@@ -1,6 +1,7 @@
1<?xml version="1.0" encoding="UTF-8"?>1<?xml version="1.0" encoding="UTF-8"?>
2<!-- Generated with glade 3.22.2 -->
2<interface>3<interface>
3 <requires lib="gtk+" version="2.16"/>4 <requires lib="gtk+" version="3.20"/>
4 <object class="GtkBox" id="stepUserInfo">5 <object class="GtkBox" id="stepUserInfo">
5 <property name="visible">True</property>6 <property name="visible">True</property>
6 <property name="can_focus">False</property>7 <property name="can_focus">False</property>
@@ -19,344 +20,514 @@
19 </packing>20 </packing>
20 </child>21 </child>
21 <child>22 <child>
22 <object class="GtkGrid" id="userinfo_table">23 <object class="GtkNotebook" id="userinfo_notebook">
23 <property name="visible">True</property>24 <property name="visible">True</property>
24 <property name="can_focus">False</property>25 <property name="can_focus">True</property>
25 <property name="border_width">20</property>26 <property name="show_tabs">False</property>
26 <property name="column_spacing">6</property>27 <property name="show_border">False</property>
27 <property name="row_spacing">6</property>
28 <child>
29 <object class="GtkLabel" id="fullname_label">
30 <property name="visible">True</property>
31 <property name="can_focus">False</property>
32 <property name="xalign">1</property>
33 <property name="label" translatable="yes">Your name:</property>
34 </object>
35 </child>
36 <child>
37 <object class="GtkLabel" id="username_label">
38 <property name="visible">True</property>
39 <property name="can_focus">False</property>
40 <property name="xalign">1</property>
41 <property name="label" translatable="yes">Pick a username:</property>
42 <property name="justify">right</property>
43 </object>
44 <packing>
45 <property name="left_attach">0</property>
46 <property name="top_attach">2</property>
47 </packing>
48 </child>
49 <child>
50 <object class="GtkLabel" id="password_label">
51 <property name="visible">True</property>
52 <property name="can_focus">False</property>
53 <property name="xalign">1</property>
54 <property name="label" translatable="yes">Choose a password:</property>
55 <property name="justify">right</property>
56 </object>
57 <packing>
58 <property name="left_attach">0</property>
59 <property name="top_attach">3</property>
60 </packing>
61 </child>
62 <child>
63 <object class="GtkLabel" id="verified_password_label">
64 <property name="visible">True</property>
65 <property name="can_focus">False</property>
66 <property name="xalign">1</property>
67 <property name="label" translatable="yes">Confirm your password:</property>
68 <property name="justify">right</property>
69 </object>
70 <packing>
71 <property name="left_attach">0</property>
72 <property name="top_attach">4</property>
73 </packing>
74 </child>
75 <child>28 <child>
76 <object class="GtkBox" id="login_vbox">29 <object class="GtkGrid" id="userinfo_table">
77 <property name="visible">True</property>30 <property name="visible">True</property>
78 <property name="can_focus">False</property>31 <property name="can_focus">False</property>
79 <property name="orientation">vertical</property>32 <property name="border_width">20</property>
80 <property name="spacing">3</property>33 <property name="row_spacing">6</property>
34 <property name="column_spacing">6</property>
81 <child>35 <child>
82 <object class="GtkRadioButton" id="login_auto">36 <object class="GtkLabel" id="fullname_label">
83 <property name="label" translatable="yes">Log in automatically</property>
84 <property name="visible">True</property>37 <property name="visible">True</property>
85 <property name="can_focus">True</property>38 <property name="can_focus">False</property>
86 <property name="receives_default">False</property>39 <property name="label" translatable="yes">Your name:</property>
87 <property name="use_action_appearance">False</property>40 <property name="xalign">1</property>
88 <property name="xalign">0</property>
89 <property name="draw_indicator">True</property>
90 <property name="group">login_pass</property>
91 </object>41 </object>
92 <packing>42 <packing>
93 <property name="expand">False</property>43 <property name="left_attach">0</property>
94 <property name="fill">False</property>44 <property name="top_attach">0</property>
95 <property name="position">0</property>
96 </packing>45 </packing>
97 </child>46 </child>
98 <child>47 <child>
99 <object class="GtkRadioButton" id="login_pass">48 <object class="GtkLabel" id="username_label">
100 <property name="label" translatable="yes">Require my password to log in</property>
101 <property name="visible">True</property>49 <property name="visible">True</property>
102 <property name="can_focus">True</property>50 <property name="can_focus">False</property>
103 <property name="receives_default">False</property>51 <property name="label" translatable="yes">Pick a username:</property>
104 <property name="use_action_appearance">False</property>52 <property name="justify">right</property>
105 <property name="xalign">0</property>53 <property name="xalign">1</property>
106 <property name="active">True</property>
107 <property name="draw_indicator">True</property>
108 </object>54 </object>
109 <packing>55 <packing>
110 <property name="expand">False</property>56 <property name="left_attach">0</property>
111 <property name="fill">False</property>57 <property name="top_attach">2</property>
112 <property name="position">1</property>
113 </packing>58 </packing>
114 </child>59 </child>
115 </object>
116 <packing>
117 <property name="left_attach">1</property>
118 <property name="top_attach">5</property>
119 </packing>
120 </child>
121 <child>
122 <object class="GtkBox" id="hbox1">
123 <property name="visible">True</property>
124 <property name="can_focus">False</property>
125 <property name="spacing">6</property>
126 <child>60 <child>
127 <object class="GtkEntry" id="password">61 <object class="GtkLabel" id="password_label">
128 <property name="visible">True</property>62 <property name="visible">True</property>
129 <property name="can_focus">True</property>63 <property name="can_focus">False</property>
130 <property name="visibility">False</property>64 <property name="label" translatable="yes">Choose a password:</property>
131 <property name="invisible_char">●</property>65 <property name="justify">right</property>
132 <property name="activates_default">True</property>66 <property name="xalign">1</property>
133 <property name="width_chars">20</property>
134 <property name="invisible_char_set">True</property>
135 <accessibility>
136 <relation type="labelled-by" target="password_label"/>
137 </accessibility>
138 <signal name="changed" handler="info_loop" swapped="no"/>
139 </object>67 </object>
140 <packing>68 <packing>
141 <property name="expand">False</property>69 <property name="left_attach">0</property>
142 <property name="fill">False</property>70 <property name="top_attach">3</property>
143 <property name="position">0</property>
144 </packing>71 </packing>
145 </child>72 </child>
146 <child>73 <child>
147 <object class="GtkLabel" id="password_strength">74 <object class="GtkLabel" id="verified_password_label">
75 <property name="visible">True</property>
148 <property name="can_focus">False</property>76 <property name="can_focus">False</property>
149 <property name="xalign">0</property>77 <property name="label" translatable="yes">Confirm your password:</property>
150 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkgreen"&gt;Strong password&lt;/span&gt;&lt;/small&gt;</property>78 <property name="justify">right</property>
151 <property name="use_markup">True</property>79 <property name="xalign">1</property>
152 </object>80 </object>
153 <packing>81 <packing>
154 <property name="expand">False</property>82 <property name="left_attach">0</property>
155 <property name="fill">False</property>83 <property name="top_attach">4</property>
156 <property name="position">1</property>
157 </packing>84 </packing>
158 </child>85 </child>
159 </object>
160 <packing>
161 <property name="left_attach">1</property>
162 <property name="top_attach">3</property>
163 </packing>
164 </child>
165 <child>
166 <object class="GtkBox" id="hbox2">
167 <property name="visible">True</property>
168 <property name="can_focus">False</property>
169 <property name="spacing">6</property>
170 <child>86 <child>
171 <object class="GtkEntry" id="verified_password">87 <object class="GtkBox" id="login_vbox">
172 <property name="visible">True</property>88 <property name="visible">True</property>
173 <property name="can_focus">True</property>89 <property name="can_focus">False</property>
174 <property name="visibility">False</property>90 <property name="orientation">vertical</property>
175 <property name="invisible_char">●</property>91 <property name="spacing">3</property>
176 <property name="activates_default">True</property>92 <child>
177 <property name="width_chars">20</property>93 <object class="GtkRadioButton" id="login_auto">
178 <property name="invisible_char_set">True</property>94 <property name="label" translatable="yes">Log in automatically</property>
179 <accessibility>95 <property name="visible">True</property>
180 <relation type="labelled-by" target="verified_password_label"/>96 <property name="can_focus">True</property>
181 </accessibility>97 <property name="receives_default">False</property>
182 <signal name="changed" handler="info_loop" swapped="no"/>98 <property name="draw_indicator">True</property>
99 <property name="group">login_pass</property>
100 </object>
101 <packing>
102 <property name="expand">False</property>
103 <property name="fill">False</property>
104 <property name="position">0</property>
105 </packing>
106 </child>
107 <child>
108 <object class="GtkRadioButton" id="login_pass">
109 <property name="label" translatable="yes">Require my password to log in</property>
110 <property name="visible">True</property>
111 <property name="can_focus">True</property>
112 <property name="receives_default">False</property>
113 <property name="active">True</property>
114 <property name="draw_indicator">True</property>
115 </object>
116 <packing>
117 <property name="expand">False</property>
118 <property name="fill">False</property>
119 <property name="position">1</property>
120 </packing>
121 </child>
183 </object>122 </object>
184 <packing>123 <packing>
185 <property name="expand">False</property>124 <property name="left_attach">1</property>
186 <property name="fill">False</property>125 <property name="top_attach">5</property>
187 <property name="position">0</property>
188 </packing>126 </packing>
189 </child>127 </child>
190 <child>128 <child>
191 <object class="GtkImage" id="password_ok">129 <object class="GtkBox" id="hbox1">
130 <property name="visible">True</property>
192 <property name="can_focus">False</property>131 <property name="can_focus">False</property>
193 <property name="stock">gtk-yes</property>132 <property name="spacing">6</property>
133 <child>
134 <object class="GtkEntry" id="password">
135 <property name="visible">True</property>
136 <property name="can_focus">True</property>
137 <property name="visibility">False</property>
138 <property name="invisible_char">●</property>
139 <property name="activates_default">True</property>
140 <property name="width_chars">20</property>
141 <signal name="changed" handler="info_loop" swapped="no"/>
142 <accessibility>
143 <relation type="labelled-by" target="password_label"/>
144 </accessibility>
145 </object>
146 <packing>
147 <property name="expand">False</property>
148 <property name="fill">False</property>
149 <property name="position">0</property>
150 </packing>
151 </child>
152 <child>
153 <object class="GtkLabel" id="password_strength">
154 <property name="can_focus">False</property>
155 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkgreen"&gt;Strong password&lt;/span&gt;&lt;/small&gt;</property>
156 <property name="use_markup">True</property>
157 <property name="xalign">0</property>
158 </object>
159 <packing>
160 <property name="expand">False</property>
161 <property name="fill">False</property>
162 <property name="position">1</property>
163 </packing>
164 </child>
194 </object>165 </object>
195 <packing>166 <packing>
196 <property name="expand">False</property>167 <property name="left_attach">1</property>
197 <property name="fill">False</property>168 <property name="top_attach">3</property>
198 <property name="position">1</property>
199 </packing>169 </packing>
200 </child>170 </child>
201 <child>171 <child>
202 <object class="GtkLabel" id="password_error_label">172 <object class="GtkBox" id="hbox2">
203 <property name="visible">True</property>173 <property name="visible">True</property>
204 <property name="can_focus">False</property>174 <property name="can_focus">False</property>
205 <property name="xalign">0</property>175 <property name="spacing">6</property>
206 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a username&lt;/span&gt;&lt;/small&gt;</property>176 <child>
207 <property name="use_markup">True</property>177 <object class="GtkEntry" id="verified_password">
178 <property name="visible">True</property>
179 <property name="can_focus">True</property>
180 <property name="visibility">False</property>
181 <property name="invisible_char">●</property>
182 <property name="activates_default">True</property>
183 <property name="width_chars">20</property>
184 <signal name="changed" handler="info_loop" swapped="no"/>
185 <accessibility>
186 <relation type="labelled-by" target="verified_password_label"/>
187 </accessibility>
188 </object>
189 <packing>
190 <property name="expand">False</property>
191 <property name="fill">False</property>
192 <property name="position">0</property>
193 </packing>
194 </child>
195 <child>
196 <object class="GtkImage" id="password_ok">
197 <property name="can_focus">False</property>
198 <property name="stock">gtk-yes</property>
199 </object>
200 <packing>
201 <property name="expand">False</property>
202 <property name="fill">False</property>
203 <property name="position">1</property>
204 </packing>
205 </child>
206 <child>
207 <object class="GtkLabel" id="password_error_label">
208 <property name="visible">True</property>
209 <property name="can_focus">False</property>
210 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a username&lt;/span&gt;&lt;/small&gt;</property>
211 <property name="use_markup">True</property>
212 <property name="xalign">0</property>
213 </object>
214 <packing>
215 <property name="expand">False</property>
216 <property name="fill">False</property>
217 <property name="position">2</property>
218 </packing>
219 </child>
208 </object>220 </object>
209 <packing>221 <packing>
210 <property name="expand">False</property>222 <property name="left_attach">1</property>
211 <property name="fill">False</property>223 <property name="top_attach">4</property>
212 <property name="position">2</property>
213 </packing>224 </packing>
214 </child>225 </child>
215 </object>
216 <packing>
217 <property name="left_attach">1</property>
218 <property name="top_attach">4</property>
219 </packing>
220 </child>
221 <child>
222 <object class="GtkBox" id="hbox3">
223 <property name="visible">True</property>
224 <property name="can_focus">False</property>
225 <property name="spacing">6</property>
226 <child>226 <child>
227 <object class="GtkEntry" id="fullname">227 <object class="GtkBox" id="hbox3">
228 <property name="visible">True</property>228 <property name="visible">True</property>
229 <property name="can_focus">True</property>229 <property name="can_focus">False</property>
230 <property name="invisible_char">•</property>230 <property name="spacing">6</property>
231 <property name="activates_default">True</property>231 <child>
232 <property name="width_chars">40</property>232 <object class="GtkEntry" id="fullname">
233 <accessibility>233 <property name="visible">True</property>
234 <relation type="labelled-by" target="fullname_label"/>234 <property name="can_focus">True</property>
235 </accessibility>235 <property name="invisible_char">•</property>
236 <signal name="changed" handler="info_loop" swapped="no"/>236 <property name="activates_default">True</property>
237 <property name="width_chars">40</property>
238 <signal name="changed" handler="info_loop" swapped="no"/>
239 <accessibility>
240 <relation type="labelled-by" target="fullname_label"/>
241 </accessibility>
242 </object>
243 <packing>
244 <property name="expand">False</property>
245 <property name="fill">False</property>
246 <property name="position">0</property>
247 </packing>
248 </child>
249 <child>
250 <object class="GtkImage" id="fullname_ok">
251 <property name="can_focus">False</property>
252 <property name="stock">gtk-yes</property>
253 </object>
254 <packing>
255 <property name="expand">False</property>
256 <property name="fill">False</property>
257 <property name="position">1</property>
258 </packing>
259 </child>
237 </object>260 </object>
238 <packing>261 <packing>
239 <property name="expand">False</property>262 <property name="left_attach">1</property>
240 <property name="fill">False</property>263 <property name="top_attach">0</property>
241 <property name="position">0</property>
242 </packing>264 </packing>
243 </child>265 </child>
244 <child>266 <child>
245 <object class="GtkImage" id="fullname_ok">267 <object class="GtkBox" id="username_box">
268 <property name="visible">True</property>
246 <property name="can_focus">False</property>269 <property name="can_focus">False</property>
247 <property name="stock">gtk-yes</property>270 <property name="spacing">6</property>
271 <child>
272 <object class="GtkEntry" id="username">
273 <property name="visible">True</property>
274 <property name="can_focus">True</property>
275 <property name="max_length">32</property>
276 <property name="invisible_char">•</property>
277 <property name="activates_default">True</property>
278 <property name="width_chars">15</property>
279 <signal name="changed" handler="info_loop" swapped="no"/>
280 <accessibility>
281 <relation type="labelled-by" target="username_label"/>
282 </accessibility>
283 </object>
284 <packing>
285 <property name="expand">False</property>
286 <property name="fill">False</property>
287 <property name="position">0</property>
288 </packing>
289 </child>
290 <child>
291 <object class="GtkImage" id="username_ok">
292 <property name="can_focus">False</property>
293 <property name="stock">gtk-yes</property>
294 </object>
295 <packing>
296 <property name="expand">False</property>
297 <property name="fill">False</property>
298 <property name="position">1</property>
299 </packing>
300 </child>
301 <child>
302 <object class="GtkLabel" id="username_error_label">
303 <property name="visible">True</property>
304 <property name="can_focus">False</property>
305 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a username&lt;/span&gt;&lt;/small&gt;</property>
306 <property name="use_markup">True</property>
307 <property name="wrap">True</property>
308 <property name="xalign">0</property>
309 </object>
310 <packing>
311 <property name="expand">False</property>
312 <property name="fill">False</property>
313 <property name="position">2</property>
314 </packing>
315 </child>
248 </object>316 </object>
249 <packing>317 <packing>
250 <property name="expand">False</property>318 <property name="left_attach">1</property>
251 <property name="fill">False</property>319 <property name="top_attach">2</property>
252 <property name="position">1</property>
253 </packing>320 </packing>
254 </child>321 </child>
255 </object>
256 <packing>
257 <property name="left_attach">1</property>
258 </packing>
259 </child>
260 <child>
261 <object class="GtkBox" id="username_box">
262 <property name="visible">True</property>
263 <property name="can_focus">False</property>
264 <property name="spacing">6</property>
265 <child>322 <child>
266 <object class="GtkEntry" id="username">323 <object class="GtkBox" id="box1">
267 <property name="visible">True</property>324 <property name="visible">True</property>
268 <property name="can_focus">True</property>325 <property name="can_focus">False</property>
269 <property name="max_length">32</property>326 <property name="orientation">vertical</property>
270 <property name="invisible_char">•</property>327 <child>
271 <property name="activates_default">True</property>328 <placeholder/>
272 <property name="width_chars">15</property>329 </child>
273 <accessibility>
274 <relation type="labelled-by" target="username_label"/>
275 </accessibility>
276 <signal name="changed" handler="info_loop" swapped="no"/>
277 </object>330 </object>
278 <packing>331 <packing>
279 <property name="expand">False</property>332 <property name="left_attach">0</property>
280 <property name="fill">False</property>333 <property name="top_attach">5</property>
281 <property name="position">0</property>
282 </packing>334 </packing>
283 </child>335 </child>
284 <child>336 <child>
285 <object class="GtkImage" id="username_ok">337 <object class="GtkBox" id="hostname_box">
338 <property name="visible">True</property>
286 <property name="can_focus">False</property>339 <property name="can_focus">False</property>
287 <property name="stock">gtk-yes</property>340 <property name="orientation">vertical</property>
341 <property name="spacing">3</property>
342 <child>
343 <object class="GtkBox" id="box3">
344 <property name="visible">True</property>
345 <property name="can_focus">False</property>
346 <property name="spacing">6</property>
347 <child>
348 <object class="GtkEntry" id="hostname">
349 <property name="visible">True</property>
350 <property name="can_focus">True</property>
351 <property name="invisible_char">•</property>
352 <signal name="changed" handler="info_loop" swapped="no"/>
353 <accessibility>
354 <relation type="labelled-by" target="hostname_label"/>
355 <relation type="labelled-by" target="hostname_extra_label"/>
356 </accessibility>
357 </object>
358 <packing>
359 <property name="expand">False</property>
360 <property name="fill">True</property>
361 <property name="position">0</property>
362 </packing>
363 </child>
364 <child>
365 <object class="GtkImage" id="hostname_ok">
366 <property name="can_focus">False</property>
367 <property name="stock">gtk-yes</property>
368 </object>
369 <packing>
370 <property name="expand">False</property>
371 <property name="fill">False</property>
372 <property name="position">1</property>
373 </packing>
374 </child>
375 <child>
376 <object class="GtkLabel" id="hostname_error_label">
377 <property name="visible">True</property>
378 <property name="can_focus">False</property>
379 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a name&lt;/span&gt;&lt;/small&gt;</property>
380 <property name="use_markup">True</property>
381 <property name="wrap">True</property>
382 </object>
383 <packing>
384 <property name="expand">False</property>
385 <property name="fill">True</property>
386 <property name="position">2</property>
387 </packing>
388 </child>
389 </object>
390 <packing>
391 <property name="expand">False</property>
392 <property name="fill">True</property>
393 <property name="position">0</property>
394 </packing>
395 </child>
396 <child>
397 <object class="GtkLabel" id="hostname_extra_label">
398 <property name="visible">True</property>
399 <property name="can_focus">False</property>
400 <property name="label" translatable="yes">The name it uses when it talks to other computers.</property>
401 <property name="xalign">0</property>
402 <attributes>
403 <attribute name="scale" value="0.83333333333333304"/>
404 </attributes>
405 </object>
406 <packing>
407 <property name="expand">False</property>
408 <property name="fill">True</property>
409 <property name="position">1</property>
410 </packing>
411 </child>
288 </object>412 </object>
289 <packing>413 <packing>
290 <property name="expand">False</property>414 <property name="left_attach">1</property>
291 <property name="fill">False</property>415 <property name="top_attach">1</property>
292 <property name="position">1</property>
293 </packing>416 </packing>
294 </child>417 </child>
295 <child>418 <child>
296 <object class="GtkLabel" id="username_error_label">419 <object class="GtkAlignment" id="alignment2">
297 <property name="visible">True</property>420 <property name="visible">True</property>
298 <property name="can_focus">False</property>421 <property name="can_focus">False</property>
299 <property name="xalign">0</property>422 <property name="bottom_padding">20</property>
300 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a username&lt;/span&gt;&lt;/small&gt;</property>423 <child>
301 <property name="use_markup">True</property>424 <object class="GtkLabel" id="hostname_label">
302 <property name="wrap">True</property>425 <property name="visible">True</property>
426 <property name="can_focus">False</property>
427 <property name="label" translatable="yes">Your computer's name:</property>
428 <property name="xalign">1</property>
429 </object>
430 </child>
303 </object>431 </object>
304 <packing>432 <packing>
305 <property name="expand">False</property>433 <property name="left_attach">0</property>
306 <property name="fill">False</property>434 <property name="top_attach">1</property>
307 <property name="position">2</property>435 </packing>
436 </child>
437 <child>
438 <object class="GtkBox">
439 <property name="visible">True</property>
440 <property name="can_focus">False</property>
441 <property name="orientation">vertical</property>
442 <property name="spacing">6</property>
443 <child>
444 <object class="GtkCheckButton" id="login_directory">
445 <property name="label" translatable="yes">Use Active Directory</property>
446 <property name="visible">True</property>
447 <property name="can_focus">True</property>
448 <property name="receives_default">False</property>
449 <property name="draw_indicator">True</property>
450 <signal name="toggled" handler="on_login_directory_toggled" swapped="no"/>
451 </object>
452 <packing>
453 <property name="expand">False</property>
454 <property name="fill">False</property>
455 <property name="position">0</property>
456 </packing>
457 </child>
458 <child>
459 <object class="GtkLabel" id="login_directory_extra_label">
460 <property name="visible">True</property>
461 <property name="can_focus">False</property>
462 <property name="label" translatable="yes"> You'll enter domain and other details in the next step.</property>
463 <property name="xalign">0</property>
464 <attributes>
465 <attribute name="scale" value="0.83333333333333304"/>
466 </attributes>
467 </object>
468 <packing>
469 <property name="expand">False</property>
470 <property name="fill">True</property>
471 <property name="position">1</property>
472 </packing>
473 </child>
474 </object>
475 <packing>
476 <property name="left_attach">1</property>
477 <property name="top_attach">6</property>
308 </packing>478 </packing>
309 </child>479 </child>
310 </object>
311 <packing>
312 <property name="left_attach">1</property>
313 <property name="top_attach">2</property>
314 </packing>
315 </child>
316 <child>
317 <object class="GtkBox" id="box1">
318 <property name="visible">True</property>
319 <property name="can_focus">False</property>
320 <property name="orientation">vertical</property>
321 <child>480 <child>
322 <placeholder/>481 <placeholder/>
323 </child>482 </child>
324 </object>483 </object>
325 <packing>484 </child>
326 <property name="left_attach">0</property>485 <child type="tab">
327 <property name="top_attach">5</property>486 <placeholder/>
328 </packing>
329 </child>487 </child>
330 <child>488 <child>
331 <object class="GtkBox" id="hostname_box">489 <object class="GtkGrid" id="directory_table">
332 <property name="visible">True</property>490 <property name="visible">True</property>
333 <property name="can_focus">False</property>491 <property name="can_focus">False</property>
334 <property name="orientation">vertical</property>492 <property name="border_width">20</property>
335 <property name="spacing">3</property>493 <property name="row_spacing">6</property>
494 <property name="column_spacing">6</property>
336 <child>495 <child>
337 <object class="GtkBox" id="box3">496 <object class="GtkLabel" id="domain_user_label">
497 <property name="visible">True</property>
498 <property name="can_focus">False</property>
499 <property name="label" translatable="yes">Domain administrator:</property>
500 <property name="justify">right</property>
501 <property name="xalign">1</property>
502 </object>
503 <packing>
504 <property name="left_attach">0</property>
505 <property name="top_attach">1</property>
506 </packing>
507 </child>
508 <child>
509 <object class="GtkBox" id="domain_user_box">
338 <property name="visible">True</property>510 <property name="visible">True</property>
339 <property name="can_focus">False</property>511 <property name="can_focus">False</property>
340 <property name="spacing">6</property>512 <property name="spacing">6</property>
341 <child>513 <child>
342 <object class="GtkEntry" id="hostname">514 <object class="GtkEntry" id="domain_user">
343 <property name="visible">True</property>515 <property name="visible">True</property>
344 <property name="can_focus">True</property>516 <property name="can_focus">True</property>
517 <property name="max_length">32</property>
345 <property name="invisible_char">•</property>518 <property name="invisible_char">•</property>
346 <accessibility>519 <property name="activates_default">True</property>
347 <relation type="labelled-by" target="hostname_label"/>520 <property name="width_chars">15</property>
348 <relation type="labelled-by" target="hostname_extra_label"/>521 <signal name="changed" handler="validate_directory_info" swapped="no"/>
349 </accessibility>
350 <signal name="changed" handler="info_loop" swapped="no"/>
351 </object>522 </object>
352 <packing>523 <packing>
353 <property name="expand">False</property>524 <property name="expand">False</property>
354 <property name="fill">True</property>525 <property name="fill">False</property>
355 <property name="position">0</property>526 <property name="position">0</property>
356 </packing>527 </packing>
357 </child>528 </child>
358 <child>529 <child>
359 <object class="GtkImage" id="hostname_ok">530 <object class="GtkImage" id="domain_user_ok">
360 <property name="can_focus">False</property>531 <property name="can_focus">False</property>
361 <property name="stock">gtk-yes</property>532 <property name="stock">gtk-yes</property>
362 </object>533 </object>
@@ -367,71 +538,163 @@
367 </packing>538 </packing>
368 </child>539 </child>
369 <child>540 <child>
370 <object class="GtkLabel" id="hostname_error_label">541 <object class="GtkLabel" id="domain_user_error_label">
371 <property name="visible">True</property>542 <property name="visible">True</property>
372 <property name="can_focus">False</property>543 <property name="can_focus">False</property>
373 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a name&lt;/span&gt;&lt;/small&gt;</property>544 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a user name&lt;/span&gt;&lt;/small&gt;</property>
374 <property name="use_markup">True</property>545 <property name="use_markup">True</property>
375 <property name="wrap">True</property>546 <property name="wrap">True</property>
547 <property name="xalign">0</property>
376 </object>548 </object>
377 <packing>549 <packing>
378 <property name="expand">False</property>550 <property name="expand">False</property>
379 <property name="fill">True</property>551 <property name="fill">False</property>
380 <property name="position">2</property>552 <property name="position">2</property>
381 </packing>553 </packing>
382 </child>554 </child>
383 </object>555 </object>
384 <packing>556 <packing>
385 <property name="expand">False</property>557 <property name="left_attach">1</property>
386 <property name="fill">True</property>558 <property name="top_attach">1</property>
387 <property name="position">0</property>
388 </packing>559 </packing>
389 </child>560 </child>
390 <child>561 <child>
391 <object class="GtkLabel" id="hostname_extra_label">562 <object class="GtkLabel" id="domain_passwd_label">
392 <property name="visible">True</property>563 <property name="visible">True</property>
393 <property name="can_focus">False</property>564 <property name="can_focus">False</property>
394 <property name="xalign">0</property>565 <property name="label" translatable="yes">Password:</property>
395 <property name="label" translatable="yes">The name it uses when it talks to other computers.</property>566 <property name="justify">right</property>
396 <attributes>567 <property name="xalign">1</property>
397 <attribute name="scale" value="0.83333333333333304"/>
398 </attributes>
399 </object>568 </object>
400 <packing>569 <packing>
401 <property name="expand">False</property>570 <property name="left_attach">0</property>
402 <property name="fill">True</property>571 <property name="top_attach">2</property>
403 <property name="position">1</property>
404 </packing>572 </packing>
405 </child>573 </child>
406 </object>
407 <packing>
408 <property name="left_attach">1</property>
409 <property name="top_attach">1</property>
410 </packing>
411 </child>
412 <child>
413 <object class="GtkAlignment" id="alignment2">
414 <property name="visible">True</property>
415 <property name="can_focus">False</property>
416 <property name="bottom_padding">20</property>
417 <child>574 <child>
418 <object class="GtkLabel" id="hostname_label">575 <object class="GtkBox" id="di_hbox">
419 <property name="visible">True</property>576 <property name="visible">True</property>
420 <property name="can_focus">False</property>577 <property name="can_focus">False</property>
578 <property name="spacing">6</property>
579 <child>
580 <object class="GtkEntry" id="domain_passwd">
581 <property name="visible">True</property>
582 <property name="can_focus">True</property>
583 <property name="visibility">False</property>
584 <property name="invisible_char">●</property>
585 <property name="activates_default">True</property>
586 <property name="width_chars">20</property>
587 <signal name="changed" handler="validate_directory_info" swapped="no"/>
588 </object>
589 <packing>
590 <property name="expand">False</property>
591 <property name="fill">False</property>
592 <property name="position">0</property>
593 </packing>
594 </child>
595 <child>
596 <placeholder/>
597 </child>
598 </object>
599 <packing>
600 <property name="left_attach">1</property>
601 <property name="top_attach">2</property>
602 </packing>
603 </child>
604 <child>
605 <object class="GtkLabel" id="domain_label">
606 <property name="visible">True</property>
607 <property name="can_focus">False</property>
608 <property name="label" translatable="yes">Domain:</property>
421 <property name="xalign">1</property>609 <property name="xalign">1</property>
422 <property name="label" translatable="yes">Your computer's name:</property>
423 </object>610 </object>
611 <packing>
612 <property name="left_attach">0</property>
613 <property name="top_attach">0</property>
614 </packing>
615 </child>
616 <child>
617 <object class="GtkBox" id="di_box">
618 <property name="visible">True</property>
619 <property name="can_focus">False</property>
620 <property name="spacing">6</property>
621 <child>
622 <object class="GtkEntry" id="domain_name">
623 <property name="visible">True</property>
624 <property name="can_focus">True</property>
625 <property name="invisible_char">•</property>
626 <signal name="changed" handler="validate_directory_info" swapped="no"/>
627 </object>
628 <packing>
629 <property name="expand">False</property>
630 <property name="fill">True</property>
631 <property name="position">0</property>
632 </packing>
633 </child>
634 <child>
635 <object class="GtkButton" id="directory_testbutton">
636 <property name="label" translatable="yes">Test connection</property>
637 <property name="visible">True</property>
638 <property name="sensitive">False</property>
639 <property name="can_focus">True</property>
640 <property name="receives_default">True</property>
641 <signal name="clicked" handler="on_testdomain_click" swapped="no"/>
642 </object>
643 <packing>
644 <property name="expand">False</property>
645 <property name="fill">True</property>
646 <property name="position">1</property>
647 </packing>
648 </child>
649 <child>
650 <object class="GtkImage" id="domain_name_ok">
651 <property name="can_focus">False</property>
652 <property name="stock">gtk-yes</property>
653 </object>
654 <packing>
655 <property name="expand">False</property>
656 <property name="fill">False</property>
657 <property name="position">2</property>
658 </packing>
659 </child>
660 <child>
661 <object class="GtkLabel" id="domain_name_error_label">
662 <property name="visible">True</property>
663 <property name="can_focus">False</property>
664 <property name="label" translatable="yes">&lt;small&gt;&lt;span color="darkred"&gt;You must enter a domain name&lt;/span&gt;&lt;/small&gt;</property>
665 <property name="use_markup">True</property>
666 <property name="wrap">True</property>
667 </object>
668 <packing>
669 <property name="expand">False</property>
670 <property name="fill">True</property>
671 <property name="position">3</property>
672 </packing>
673 </child>
674 </object>
675 <packing>
676 <property name="left_attach">1</property>
677 <property name="top_attach">0</property>
678 </packing>
424 </child>679 </child>
425 </object>680 </object>
426 <packing>681 <packing>
427 <property name="left_attach">0</property>682 <property name="position">1</property>
428 <property name="top_attach">1</property>
429 </packing>683 </packing>
430 </child>684 </child>
685 <child type="tab">
686 <placeholder/>
687 </child>
688 <child>
689 <placeholder/>
690 </child>
691 <child type="tab">
692 <placeholder/>
693 </child>
431 </object>694 </object>
432 <packing>695 <packing>
433 <property name="expand">False</property>696 <property name="expand">False</property>
434 <property name="fill">False</property>697 <property name="fill">True</property>
435 <property name="position">1</property>698 <property name="position">1</property>
436 </packing>699 </packing>
437 </child>700 </child>
diff --git a/scripts/plugininstall.py b/scripts/plugininstall.py
index e9acdc9..434fd3b 100755
--- a/scripts/plugininstall.py
+++ b/scripts/plugininstall.py
@@ -228,6 +228,10 @@ class Install(install_misc.InstallBase):
228 self.configure_zsys()228 self.configure_zsys()
229229
230 self.next_region()230 self.next_region()
231 self.db.progress('INFO', 'ubiquity/install/activedirectory')
232 self.configure_active_directory()
233
234 self.next_region()
231 self.db.progress('INFO', 'ubiquity/install/bootloader')235 self.db.progress('INFO', 'ubiquity/install/bootloader')
232 self.copy_mok()236 self.copy_mok()
233 self.configure_bootloader()237 self.configure_bootloader()
@@ -968,6 +972,72 @@ class Install(install_misc.InstallBase):
968 if use_zfs:972 if use_zfs:
969 misc.execute_root('/usr/share/ubiquity/zsys-setup', 'finalize')973 misc.execute_root('/usr/share/ubiquity/zsys-setup', 'finalize')
970974
975 def configure_active_directory(self):
976 """ Join Active Directory domain and enable pam_mkhomedir """
977 use_directory = self.db.get('ubiquity/login_use_directory')
978 if use_directory != 'true':
979 return
980
981 from socket import gethostname
982 hostname_cur = gethostname()
983 hostname_new = ''
984 with open(self.target_file('etc/hostname'), 'r') as f:
985 hostname_new = f.read().strip()
986
987 # Set hostname for AD to determine FQDN (no fqdn option in realm join, only adcli)
988 misc.execute_root('hostname', hostname_new)
989
990 directory_domain = self.db.get('ubiquity/directory_domain')
991 directory_user = self.db.get('ubiquity/directory_user')
992 directory_passwd = self.db.get('ubiquity/directory_passwd')
993
994 binds = ("/proc", "/sys", "/dev", "/run")
995 try:
996 for bind in binds:
997 misc.execute('mount', '--bind', bind, self.target + bind)
998 # join AD on host (services are running on host)
999 if not self.join_domain(hostname_new, directory_domain, directory_user, directory_passwd):
1000 self.db.input('critical', 'ubiquity/install/broken_active_directory')
1001 self.db.go()
1002 finally:
1003 for bind in binds:
1004 misc.execute('umount', '-f', self.target + bind)
1005 # Reset hostname
1006 misc.execute_root('hostname', hostname_cur)
1007
1008 # Enable pam_mkhomedir
1009 try:
1010 subprocess.check_call(['chroot', self.target, 'pam-auth-update',
1011 '--package', '--enable', 'mkhomedir'],
1012 preexec_fn=install_misc.debconf_disconnect)
1013 except subprocess.CalledProcessError:
1014 self.db.input('critical', 'ubiquity/install/broken_active_directory')
1015 self.db.go()
1016
1017 def join_domain(self, hostname, directory_domain, directory_user, directory_passwd):
1018 """ Join an Active Directory domain """
1019 log_args = ['log-output', '-t', 'ubiquity']
1020 log_args.extend(['realm', 'join', '--install', self.target,
1021 '--user', directory_user, '--computer-name', hostname,
1022 '--unattended', directory_domain])
1023 try:
1024 p = subprocess.run(log_args, input=directory_passwd, timeout=60, encoding="utf-8")
1025 except TimeoutError as e:
1026 syslog.syslog(syslog.LOG_ERR, ' '.join(log_args))
1027 syslog.syslog(syslog.LOG_ERR, "Command timed out(%s): %s" % (e.errno, e.strerror))
1028 return False
1029 except IOError as e:
1030 syslog.syslog(syslog.LOG_ERR, ' '.join(log_args))
1031 syslog.syslog(syslog.LOG_ERR, "OS error(%s): %s" % (e.errno, e.strerror))
1032 return False
1033
1034 if p.returncode != 0:
1035 syslog.syslog(syslog.LOG_ERR, ' '.join(log_args))
1036 return False
1037
1038 syslog.syslog(' '.join(log_args))
1039 return True
1040
971 def copy_mok(self):1041 def copy_mok(self):
972 if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:1042 if 'UBIQUITY_OEM_USER_CONFIG' in os.environ:
973 return1043 return
diff --git a/tests/test_usersetup.py b/tests/test_usersetup.py
index 0d6c178..33f4949 100644
--- a/tests/test_usersetup.py
+++ b/tests/test_usersetup.py
@@ -41,6 +41,7 @@ class UserSetupTests(unittest.TestCase):
41 error_msg = 'That name already exists on the network.'41 error_msg = 'That name already exists on the network.'
42 self.gtk.resolver = UbiquityMockResolver.MockResolver(42 self.gtk.resolver = UbiquityMockResolver.MockResolver(
43 hostname='myhostname')43 hostname='myhostname')
44 self.gtk.plugin_translate('en')
44 self.gtk.hostname_ok.show()45 self.gtk.hostname_ok.show()
45 self.gtk.hostname.set_text('myhostname')46 self.gtk.hostname.set_text('myhostname')
46 self.gtk.hostname_error = mock.Mock()47 self.gtk.hostname_error = mock.Mock()
diff --git a/ubiquity/components/plugininstall.py b/ubiquity/components/plugininstall.py
index 213b57e..dcb04d6 100644
--- a/ubiquity/components/plugininstall.py
+++ b/ubiquity/components/plugininstall.py
@@ -65,6 +65,8 @@ class Install(FilteredCommand):
65 return True65 return True
66 elif question == 'apt-setup/security-updates-failed':66 elif question == 'apt-setup/security-updates-failed':
67 fatal = False67 fatal = False
68 elif question == 'ubiquity/install/broken_active_directory':
69 fatal = False
68 else:70 else:
69 fatal = True71 fatal = True
70 self.frontend.error_dialog(self.description(question),72 self.frontend.error_dialog(self.description(question),
diff --git a/ubiquity/frontend/gtk_ui.py b/ubiquity/frontend/gtk_ui.py
index 7280f96..c3a7dea 100644
--- a/ubiquity/frontend/gtk_ui.py
+++ b/ubiquity/frontend/gtk_ui.py
@@ -1887,14 +1887,22 @@ class Wizard(BaseFrontend):
1887 msg = title1887 msg = title
1888 dialog = Gtk.MessageDialog(1888 dialog = Gtk.MessageDialog(
1889 self.live_installer, Gtk.DialogFlags.MODAL,1889 self.live_installer, Gtk.DialogFlags.MODAL,
1890 Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, msg)1890 Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, "")
1891 dialog.set_title(title)1891 dialog.set_title(title)
1892 dialog.set_markup(msg)
1893 for label in dialog.get_message_area().get_children():
1894 if not isinstance(label, Gtk.Label):
1895 continue
1896 label.connect('activate-link', self.on_link_clicked)
1892 dialog.run()1897 dialog.run()
1893 self.set_busy_cursor(saved_busy_cursor)1898 self.set_busy_cursor(saved_busy_cursor)
1894 dialog.hide()1899 dialog.hide()
1895 if fatal:1900 if fatal:
1896 self.return_to_partitioning()1901 self.return_to_partitioning()
18971902
1903 def on_link_clicked(self, widget, uri):
1904 misc.launch_uri(uri)
1905
1898 def toggle_grub_fail(self, unused_widget):1906 def toggle_grub_fail(self, unused_widget):
1899 if self.grub_no_new_device.get_active():1907 if self.grub_no_new_device.get_active():
1900 self.no_grub_warn.show()1908 self.no_grub_warn.show()
diff --git a/ubiquity/plugins/ubi-usersetup.py b/ubiquity/plugins/ubi-usersetup.py
index 57f2a35..b61d74a 100644
--- a/ubiquity/plugins/ubi-usersetup.py
+++ b/ubiquity/plugins/ubi-usersetup.py
@@ -31,7 +31,7 @@ import re
3131
32import debconf32import debconf
3333
34from ubiquity import misc, plugin, validation34from ubiquity import i18n, misc, plugin, validation
3535
3636
37NAME = 'usersetup'37NAME = 'usersetup'
@@ -146,6 +146,10 @@ class PageBase(plugin.PluginUI):
146 def set_allow_password_empty(self, empty):146 def set_allow_password_empty(self, empty):
147 self.allow_password_empty = empty147 self.allow_password_empty = empty
148148
149 def plugin_translate(self, lang):
150 self.hostname_error_text = i18n.get_string('hostname_error', lang)
151 self.domain_connection_error_text = i18n.get_string('domain_connection_error', lang)
152
149153
150class PageGtk(PageBase):154class PageGtk(PageBase):
151 plugin_title = 'ubiquity/text/userinfo_heading_label'155 plugin_title = 'ubiquity/text/userinfo_heading_label'
@@ -186,6 +190,19 @@ class PageGtk(PageBase):
186 self.password_ok = builder.get_object('password_ok')190 self.password_ok = builder.get_object('password_ok')
187 self.password_strength = builder.get_object('password_strength')191 self.password_strength = builder.get_object('password_strength')
188192
193 self.login_directory = builder.get_object('login_directory')
194 self.login_directory_extra_label = builder.get_object('login_directory_extra_label')
195 self.domain_name = builder.get_object('domain_name')
196 self.domain_name_ok = builder.get_object('domain_name_ok')
197 self.domain_name_error_label = builder.get_object('domain_name_error_label')
198 self.domain_user = builder.get_object('domain_user')
199 self.domain_user_ok = builder.get_object('domain_user_ok')
200 self.domain_user_error_label = builder.get_object('domain_user_error_label')
201 self.domain_passwd = builder.get_object('domain_passwd')
202 self.directory_testbutton = builder.get_object('directory_testbutton')
203
204 self.userinfo_notebook = builder.get_object('userinfo_notebook')
205
189 # Dodgy hack to let us center the contents of the page without it206 # Dodgy hack to let us center the contents of the page without it
190 # moving as elements appear and disappear, specifically the full name207 # moving as elements appear and disappear, specifically the full name
191 # okay check icon and the hostname error messages.208 # okay check icon and the hostname error messages.
@@ -204,6 +221,11 @@ class PageGtk(PageBase):
204 self.hostname_changed_id = self.hostname.connect(221 self.hostname_changed_id = self.hostname.connect(
205 'changed', self.on_hostname_changed)222 'changed', self.on_hostname_changed)
206223
224 if not os.path.exists('/usr/sbin/realm'):
225 self.login_directory.hide()
226 self.login_directory_extra_label.hide()
227 self.login_directory_extra_label.set_sensitive(False)
228
207 if self.controller.oem_config:229 if self.controller.oem_config:
208 self.fullname.set_text('OEM Configuration (temporary user)')230 self.fullname.set_text('OEM Configuration (temporary user)')
209 self.fullname.set_editable(False)231 self.fullname.set_editable(False)
@@ -272,11 +294,41 @@ class PageGtk(PageBase):
272 def set_hostname(self, value):294 def set_hostname(self, value):
273 self.hostname.set_text(value)295 self.hostname.set_text(value)
274296
297 def get_login_directory(self):
298 """ Use a directory for authentication """
299 return self.login_directory.get_active()
300
301 def get_domain_name(self):
302 """ Get the domain name """
303 return self.domain_name.get_text()
304
305 def get_domain_user(self):
306 """ Get the domain name """
307 return self.domain_user.get_text()
308
309 def get_domain_passwd(self):
310 """ Get the domain name """
311 return self.domain_passwd.get_text()
312
313 def domain_name_error(self, msg):
314 self.domain_name_ok.hide()
315 m = '<small><span foreground="darkred"><b>%s</b></span></small>' % msg
316 self.domain_name_error_label.set_markup(m)
317 self.domain_name_error_label.show()
318
319 def domain_user_error(self, msg):
320 self.domain_user_ok.hide()
321 m = '<small><span foreground="darkred"><b>%s</b></span></small>' % msg
322 self.domain_user_error_label.set_markup(m)
323 self.domain_user_error_label.show()
324
275 def clear_errors(self):325 def clear_errors(self):
276 self.username_error_label.hide()326 self.username_error_label.hide()
277 self.hostname_error_label.hide()327 self.hostname_error_label.hide()
278 self.password_error_label.hide()328 self.password_error_label.hide()
279329
330 self.domain_name_error_label.hide()
331
280 # Callback functions.332 # Callback functions.
281333
282 def info_loop(self, widget):334 def info_loop(self, widget):
@@ -380,8 +432,7 @@ class PageGtk(PageBase):
380 except GLib.GError:432 except GLib.GError:
381 pass433 pass
382 else:434 else:
383 # FIXME: i18n435 self.hostname_error(self.hostname_error_text)
384 self.hostname_error('That name already exists on the network.')
385 self.hostname_ok.hide()436 self.hostname_ok.hide()
386437
387 def hostname_timeout(self, widget):438 def hostname_timeout(self, widget):
@@ -407,6 +458,91 @@ class PageGtk(PageBase):
407 else:458 else:
408 self.resolver_ok = False459 self.resolver_ok = False
409460
461 def validate_directory_info(self, widget=None):
462 """ Validate domain information """
463 domain_name_is_valid = True
464 domain_info_complete = True
465
466 domain_name_txt = self.domain_name.get_text().strip()
467 domain_user_txt = self.domain_user.get_text()
468 domain_passwd_txt = self.domain_passwd.get_text()
469
470 self.domain_name_ok.hide()
471 if domain_name_txt:
472 errors = check_hostname(domain_name_txt)
473 if errors:
474 self.domain_name_error(make_error_string(self.controller, errors))
475 domain_name_is_valid = False
476 else:
477 self.domain_name_error_label.hide()
478 else:
479 self.domain_name_error_label.hide()
480 domain_name_is_valid = False
481 self.directory_testbutton.set_sensitive(domain_name_is_valid)
482 domain_info_complete = domain_name_is_valid
483
484 if domain_user_txt:
485 # Don't enforce lower case for AD administrator.
486 errors = check_username(domain_user_txt.lower())
487 if errors:
488 self.domain_user_error(make_error_string(self.controller, errors))
489 domain_info_complete = False
490 else:
491 self.domain_user_ok.show()
492 self.domain_user_error_label.hide()
493 else:
494 self.domain_user_ok.hide()
495 self.domain_user_error_label.hide()
496 domain_info_complete = False
497
498 if not domain_passwd_txt:
499 domain_info_complete = False
500
501 self.controller.allow_go_forward(domain_info_complete)
502
503 def switch_userinfo_tab(self, tab):
504 self.userinfo_notebook.set_current_page(tab)
505
506 if tab == 1:
507 self.title = 'ubiquity/text/directory_information_title'
508 self.controller.allow_go_backward(True)
509 self.validate_directory_info()
510 else:
511 self.title = self.plugin_title
512 self.controller.allow_go_backward(False)
513 self.controller.allow_go_forward(True)
514
515 self.controller._wizard.set_page_title(self)
516
517 def plugin_set_online_state(self, state):
518 if not state:
519 self.login_directory.set_active(False)
520 self.login_directory.set_sensitive(state)
521
522 def plugin_on_next_clicked(self):
523 if self.userinfo_notebook.get_current_page() == 0 and self.get_login_directory():
524 self.switch_userinfo_tab(1)
525 return True
526 return False
527
528 def plugin_on_back_clicked(self):
529 if self.userinfo_notebook.get_current_page() == 1:
530 self.switch_userinfo_tab(0)
531 return True
532 return False
533
534 def on_testdomain_click(self, widget):
535 if misc.execute('realm', 'discover', self.domain_name.get_text()):
536 self.domain_name_ok.show()
537 self.domain_name_error_label.hide()
538 else:
539 self.domain_name_ok.hide()
540 self.domain_name_error(self.domain_connection_error_text)
541 self.domain_name_error_label.show()
542
543 def on_login_directory_toggled(self, widget):
544 self.login_directory_extra_label.set_sensitive(widget.get_active())
545
410546
411class PageKde(PageBase):547class PageKde(PageBase):
412 plugin_breadcrumb = 'ubiquity/text/breadcrumb_user'548 plugin_breadcrumb = 'ubiquity/text/breadcrumb_user'
@@ -746,6 +882,13 @@ class Page(plugin.Plugin):
746 else:882 else:
747 self.preseed('netcfg/get_domain', '')883 self.preseed('netcfg/get_domain', '')
748884
885 if hasattr(self.ui, 'get_login_directory'):
886 self.preseed_bool('ubiquity/login_use_directory', self.ui.get_login_directory())
887 if self.ui.get_login_directory():
888 self.preseed('ubiquity/directory_domain', self.ui.get_domain_name())
889 self.preseed('ubiquity/directory_user', self.ui.get_domain_user())
890 self.preseed('ubiquity/directory_passwd', self.ui.get_domain_passwd())
891
749 plugin.Plugin.ok_handler(self)892 plugin.Plugin.ok_handler(self)
750893
751 def error(self, priority, question):894 def error(self, priority, question):

Subscribers

People subscribed via source and target branches