2
# Copyright (c) 2010 Canonical
4
# Author: Oliver Grawert <ogra@canonical.com>
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of the GNU General Public License as
8
# published by the Free Software Foundation; either version 2 of the
9
# License, or (at your option) any later version.
11
# This program is distributed in the hope that it will be useful,
12
# but WITHOUT ANY WARRANTY; without even the implied warranty of
13
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
# GNU General Public License for more details.
16
# You should have received a copy of the GNU General Public License
17
# along with this program; if not, write to the Free Software
18
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21
######################################################################
26
from subprocess import Popen,PIPE,call,STDOUT
29
from gettext import gettext as _
33
releases = ['lucid', 'karmic', 'jaunty']
38
DIR="/usr/share/locale"
40
gettext.bindtextdomain(APP, DIR)
41
gettext.textdomain(APP)
44
self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
45
self.window.connect("destroy", self.destroy)
46
self.window.set_size_request(400, 380)
51
filem = gtk.MenuItem(_('File'))
52
filem.set_submenu(filemenu)
54
gtk.stock_add([(gtk.STOCK_OPEN, _('Load Profile'), 0, 0, "")])
55
open_prof = gtk.ImageMenuItem(gtk.STOCK_OPEN, None)
56
open_prof.connect("activate", self.open_profile)
57
filemenu.append(open_prof)
59
gtk.stock_add([(gtk.STOCK_SAVE, _('Save Profile'), 0, 0, "")])
60
save_prof = gtk.ImageMenuItem(gtk.STOCK_SAVE, None)
61
save_prof.connect("activate", self.save_profile)
62
filemenu.append(save_prof)
64
sep = gtk.SeparatorMenuItem()
67
exit = gtk.ImageMenuItem(gtk.STOCK_QUIT, None)
68
exit.connect("activate", gtk.main_quit)
75
tf.set_label(_('General Options'))
76
top_table = gtk.Table(5, 2, False)
79
mirrorlabel = gtk.Label(_('Mirror'))
80
mirrorlabel.set_alignment(xalign=0, yalign=0.5)
81
self.mirrorentry = gtk.Entry()
82
self.mirrorentry.insert_text("http://ports.ubuntu.com/ubuntu-ports", 0)
83
self.mirrorentry.set_position(-1)
84
top_table.attach(mirrorlabel, 0, 1, 0, 1)
85
top_table.attach(self.mirrorentry, 1, 2, 0, 1)
87
self.xmirror = gtk.CheckButton(_('Use additional mirror'))
88
self.xmirrorentry = gtk.Entry()
89
self.xmirrorentry.set_sensitive(False)
90
self.xmirror.connect("toggled", self.set_sensitivity)
91
top_table.attach(self.xmirror, 0, 1, 1, 2)
92
top_table.attach(self.xmirrorentry, 1, 2, 1, 2)
94
releaselabel = gtk.Label(_('Release'))
95
releaselabel.set_alignment(xalign=0, yalign=0.5)
96
self.releaseselect = gtk.combo_box_new_text()
97
for release in releases:
98
self.releaseselect.append_text(release)
99
self.releaseselect.set_active(0)
100
top_table.attach(releaselabel, 0, 1, 2, 3)
101
top_table.attach(self.releaseselect, 1, 2, 2, 3)
103
scriptlabel = gtk.Label(_('Custom post installation script'))
104
scriptlabel.set_alignment(xalign=0, yalign=0.5)
105
gtk.stock_add([(gtk.STOCK_OPEN, _('Load Script'), 0, 0, "")])
106
self.scriptfile = gtk.FileChooserButton(_('Select script file'), None)
107
top_table.attach(scriptlabel, 0, 1, 3, 4)
108
top_table.attach(self.scriptfile, 1, 2, 3, 4)
110
imgsizelabel = gtk.Label(_('Rootfs build Space'))
111
imgsizelabel.set_alignment(xalign=0, yalign=0.5)
112
imgsizebox = gtk.HBox(False,0)
113
self.imgsize = gtk.Adjustment(4, 1, 100, 1, 0, 0)
114
imgsizespin = gtk.SpinButton(self.imgsize, 1, 0)
115
imgsizeunit = gtk.Label("Gigabyte")
116
imgsizeunit.set_alignment(xalign=0, yalign=0.5)
117
imgsizebox.add(imgsizespin)
118
imgsizebox.add(imgsizeunit)
119
top_table.attach(imgsizelabel, 0, 1, 4, 5)
120
top_table.attach(imgsizebox, 1, 2, 4, 5)
124
mf.set_label(_('Options for packages to install'))
125
middle_table = gtk.Table(3, 2, False)
128
pkglistlabel = gtk.Label(_('Use a list of packages'))
129
pkglistlabel.set_alignment(xalign=0, yalign=0.5)
130
self.pkglistentry = gtk.Entry()
131
self.pkglistentry.insert_text("ubuntu-minimal", 0)
132
middle_table.attach(pkglistlabel, 0, 1, 1, 2)
133
middle_table.attach(self.pkglistentry, 1, 2, 1, 2)
135
tasklabel = gtk.Label(_('Select an Ubuntu task'))
136
tasklabel.set_alignment(xalign=0, yalign=0.5)
137
tasksel = gtk.Button(_('Run Tasksel'))
138
tasksel.connect("clicked", self.run_tasksel)
139
middle_table.attach(tasklabel, 0, 1, 2, 3)
140
middle_table.attach(tasksel, 1, 2, 2, 3)
142
seedfilelabel = gtk.Label(_('Use a seed file'))
143
seedfilelabel.set_alignment(xalign=0, yalign=0.5)
144
gtk.stock_add([(gtk.STOCK_OPEN, _('Load Seed File'), 0, 0, "")])
145
self.seedfile = gtk.FileChooserButton(_('Select seed file'), None)
146
middle_table.attach(seedfilelabel, 0, 1, 3, 4)
147
middle_table.attach(self.seedfile, 1, 2, 3, 4)
151
bf.set_label(_('Advanced Options'))
152
bottom_table = gtk.Table(2, 2, False)
155
seriallabel = gtk.Label(_('Use serial device in rootfs'))
156
seriallabel.set_alignment(xalign=0, yalign=0.5)
157
self.serialentry = gtk.Entry()
158
bottom_table.attach(seriallabel, 0, 1, 1, 2)
159
bottom_table.attach(self.serialentry, 1, 2, 1, 2)
161
#partitionlabel = gtk.Label(_('Partition to unpack rootfs to'))
162
#partitionlabel.set_alignment(xalign=0, yalign=0.5)
163
#self.partitionentry = gtk.Entry()
164
#bottom_table.attach(partitionlabel, 0, 1, 2, 3)
165
#bottom_table.attach(self.partitionentry, 1, 2, 2, 3)
168
bb = gtk.HBox(False,0)
170
gtk.stock_add([(gtk.STOCK_EXECUTE, _('Build'), 0, 0, "")])
171
button1 = gtk.Button(None, stock=gtk.STOCK_EXECUTE)
172
button1.connect("clicked", self.run_build)
174
button2 = gtk.Button(None, stock=gtk.STOCK_CANCEL)
175
button2.connect("clicked", gtk.main_quit)
177
bb.pack_end(button1, False, False, 0)
178
bb.pack_end(button2, False, False, 0)
181
mainbox = gtk.VBox(False, 0)
182
mainbox.pack_start(mb, False, False, 5)
183
mainbox.pack_start(tf, False, False, 5)
184
mainbox.pack_start(mf, False, False, 5)
185
mainbox.pack_start(bf, False, False, 5)
186
mainbox.pack_start(bb, False, False, 5)
188
self.window.add(mainbox)
190
self.window.show_all()
192
def set_sensitivity(self, widget):
193
self.xmirrorentry.set_text("")
194
self.xmirrorentry.set_sensitive(self.xmirror.get_active())
196
def run_build(self, widget):
197
command = ['cd /tmp;','rootstock -f rootstockfs']
198
if self.mirrorentry.get_text():
199
command.append(' -m '+self.mirrorentry.get_text())
200
if self.xmirrorentry.get_text():
201
command.append(' --extra-mirror '+self.xmirrorentry.get_text())
202
command.append(' -d '+releases[self.releaseselect.get_active()])
203
if self.scriptfile.get_filename() != None:
204
command.append(' --script '+str(self.scriptfile.get_filename()))
205
command.append(' -i '+str(int(self.imgsize.get_value()))+'G')
206
if self.pkglistentry.get_text():
207
command.append(' -s '+self.pkglistentry.get_text()+' '+str(self.tasks))
208
if self.seedfile.get_filename() != None:
209
command.append(' --manifest '+str(self.seedfile.get_filename()))
210
if self.serialentry.get_text():
211
command.append(' --serial '+self.serialentry.get_text())
212
while gtk.events_pending():
213
gtk.main_iteration(True)
214
#print 'Target partition: '+self.partitionentry.get_text()
215
self.draw_progress_win()
216
self.run_command(command)
218
def draw_progress_win(self):
219
while gtk.events_pending():
220
gtk.main_iteration(True)
221
self.window.set_sensitive(False)
222
prgwin = gtk.Window(gtk.WINDOW_TOPLEVEL)
223
prgwin.set_transient_for(self.window)
224
prgwin.connect("destroy", self.close_progress)
225
prgwin.set_title(_('Building rootfs'))
227
prgwin.set_size_request(300, 80)
229
hbox = gtk.HBox(False, 5)
230
vbox = gtk.VBox(False, 5)
232
self.progress = gtk.ProgressBar()
233
vbox.pack_start(self.progress, False, False, 5)
235
self.closebut = gtk.Button(None, stock=gtk.STOCK_CANCEL)
236
self.closebut.connect("clicked", self.close_progress)
238
hbox.pack_start(dummy, True, True, 5)
239
hbox.pack_start(self.closebut, False, False, 5)
241
vbox.pack_start(hbox, False, False, 5)
246
def run_command(self, command):
250
cmdstr=cmdstr+' '+item
251
output = Popen([cmdstr], stdout=PIPE, stderr=STDOUT, shell=True)
252
self.rootstockpid = output.pid
253
while output.stdout.readline():
254
line = output.stdout.readline().strip()
255
while gtk.events_pending():
256
gtk.main_iteration(True)
257
self.progress.set_fraction(float(lines/1000))
258
self.progress.set_text(line)
259
if line.startswith("I: ARM rootfs created"):
261
self.tarball = line.split('/')[1]
264
elif line.startswith('Kernel panic'):
266
self.error('rootstock died, please see the log')
268
pid, sts = os.waitpid(output.pid, 0)
269
self.progress.set_fraction(1.0)
271
self.error('rootstock died')
272
print "rootstock died !"
274
def close_progress(self, widget):
275
while gtk.events_pending():
276
gtk.main_iteration(True)
277
if self.rootstockpid:
278
os.kill(self.rootstockpid+1, 6)
279
pid, sts = os.waitpid(self.rootstockpid, 0)
280
widget.get_parent_window().hide()
281
self.window.set_sensitive(True)
283
widget.get_parent_window().hide()
284
self.window.set_sensitive(True)
286
def error(self, string):
287
dialog = gtk.Dialog('Error',
289
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
290
(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
291
dialog.vbox.pack_start(gtk.Label(string))
293
result = dialog.run()
298
dialog = gtk.Dialog('Successfully built rootfs',
300
gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
301
(gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
302
dialog.vbox.pack_start(gtk.Label('The rootfe tarball was created in '+self.tarball))
304
result = dialog.run()
308
def run_tasksel(self, widget):
309
self.tasks = Popen(["/usr/lib/rootstock/rootstock-tasksel"], stdout=PIPE).communicate()[0].rstrip()
311
def open_profile(self, widget):
314
def save_profile(self, widget):
317
def destroy(self, widget, data=None):
323
if __name__ == "__main__":