~ubuntu-branches/ubuntu/oneiric/rootstock/oneiric

« back to all changes in this revision

Viewing changes to gui/bin/rootstock-gtk

  • Committer: Bazaar Package Importer
  • Author(s): Oliver Grawert
  • Date: 2010-02-17 21:48:44 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20100217214844-pn343g5w5oahkw7m
Tags: 0.1.99-0ubuntu1
* new upstream release (pre 0.2.0)
 - includes fixes for the following bugs (LP: #461668)
   (LP: #437634), (LP: #515787)
 - adds a new binary package for the gtk UI
 - support for --manifest files
 - support for caching packages to do subsequent offline builds
 - adds --extra-mirror option
 - prepared for using the ubuntu archive versatile kernel
 - optional --script support was added for adding oem scripts
 - defaults to installing oem-config in all rootfses now for user, timezone,
   keyboard and language configuration on first boot
 - the gtk UI has support for tasksel package selection

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#!/usr/bin/python
 
2
#  Copyright (c) 2010 Canonical
 
3
#
 
4
#  Author: Oliver Grawert <ogra@canonical.com>
 
5
#
 
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.
 
10
#
 
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.
 
15
#
 
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
 
19
#  USA
 
20
#
 
21
######################################################################
 
22
 
 
23
import pygtk
 
24
pygtk.require('2.0')
 
25
import gtk
 
26
from subprocess import Popen,PIPE,call,STDOUT
 
27
 
 
28
import gettext
 
29
from gettext import gettext as _
 
30
 
 
31
import os
 
32
 
 
33
releases = ['lucid', 'karmic', 'jaunty']
 
34
 
 
35
class MainWin:
 
36
    def __init__(self):
 
37
        APP="rootstock-gtk"
 
38
        DIR="/usr/share/locale"
 
39
 
 
40
        gettext.bindtextdomain(APP, DIR)
 
41
        gettext.textdomain(APP)
 
42
 
 
43
        self.tasks = ""
 
44
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
 
45
        self.window.connect("destroy", self.destroy)
 
46
        self.window.set_size_request(400, 380)
 
47
 
 
48
        # the menubar
 
49
        mb = gtk.MenuBar()
 
50
        filemenu = gtk.Menu()
 
51
        filem = gtk.MenuItem(_('File'))
 
52
        filem.set_submenu(filemenu)
 
53
 
 
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)
 
58
 
 
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)
 
63
 
 
64
        sep = gtk.SeparatorMenuItem()
 
65
        filemenu.append(sep)
 
66
 
 
67
        exit = gtk.ImageMenuItem(gtk.STOCK_QUIT, None)
 
68
        exit.connect("activate", gtk.main_quit)
 
69
        filemenu.append(exit)
 
70
 
 
71
        mb.append(filem)
 
72
 
 
73
        # topframe
 
74
        tf = gtk.Frame()
 
75
        tf.set_label(_('General Options'))
 
76
        top_table = gtk.Table(5, 2, False)
 
77
        tf.add(top_table)
 
78
 
 
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)
 
86
 
 
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)
 
93
 
 
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)
 
102
 
 
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)
 
109
 
 
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)
 
121
 
 
122
        # middleframe
 
123
        mf = gtk.Frame()
 
124
        mf.set_label(_('Options for packages to install'))
 
125
        middle_table = gtk.Table(3, 2, False)
 
126
        mf.add(middle_table)
 
127
 
 
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)
 
134
 
 
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)
 
141
 
 
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)
 
148
 
 
149
        # bottomframe
 
150
        bf = gtk.Frame()
 
151
        bf.set_label(_('Advanced Options'))
 
152
        bottom_table = gtk.Table(2, 2, False)
 
153
        bf.add(bottom_table)
 
154
 
 
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)
 
160
 
 
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)
 
166
 
 
167
        # buttonbar
 
168
        bb = gtk.HBox(False,0)
 
169
 
 
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)
 
173
 
 
174
        button2 = gtk.Button(None, stock=gtk.STOCK_CANCEL)
 
175
        button2.connect("clicked", gtk.main_quit)
 
176
 
 
177
        bb.pack_end(button1, False, False, 0)
 
178
        bb.pack_end(button2, False, False, 0)
 
179
 
 
180
        # toplevel layout
 
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)
 
187
 
 
188
        self.window.add(mainbox)
 
189
 
 
190
        self.window.show_all()
 
191
 
 
192
    def set_sensitivity(self, widget):
 
193
        self.xmirrorentry.set_text("")
 
194
        self.xmirrorentry.set_sensitive(self.xmirror.get_active())
 
195
 
 
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)
 
217
 
 
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'))
 
226
 
 
227
        prgwin.set_size_request(300, 80)
 
228
 
 
229
        hbox = gtk.HBox(False, 5)
 
230
        vbox = gtk.VBox(False, 5)
 
231
 
 
232
        self.progress = gtk.ProgressBar()
 
233
        vbox.pack_start(self.progress, False, False, 5)
 
234
 
 
235
        self.closebut = gtk.Button(None, stock=gtk.STOCK_CANCEL)
 
236
        self.closebut.connect("clicked", self.close_progress)
 
237
        dummy = gtk.Label()
 
238
        hbox.pack_start(dummy, True, True, 5)
 
239
        hbox.pack_start(self.closebut, False, False, 5)
 
240
 
 
241
        vbox.pack_start(hbox, False, False, 5)
 
242
 
 
243
        prgwin.add(vbox)
 
244
        prgwin.show_all()
 
245
 
 
246
    def run_command(self, command):
 
247
        cmdstr = ""
 
248
        lines = 1.0
 
249
        for item in 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"):
 
260
                print line
 
261
                self.tarball = line.split('/')[1]
 
262
                self.close_progress
 
263
                self.success
 
264
            elif line.startswith('Kernel panic'):
 
265
                self.close_progress
 
266
                self.error('rootstock died, please see the log')
 
267
            lines += 1
 
268
        pid, sts = os.waitpid(output.pid, 0)
 
269
        self.progress.set_fraction(1.0)
 
270
        if sts != 0:
 
271
            self.error('rootstock died')
 
272
            print "rootstock died !"
 
273
 
 
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)
 
282
        else:
 
283
            widget.get_parent_window().hide()
 
284
            self.window.set_sensitive(True)
 
285
 
 
286
    def error(self, string):
 
287
        dialog = gtk.Dialog('Error',
 
288
                self.window,
 
289
                gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
 
290
                (gtk.STOCK_OK, gtk.RESPONSE_ACCEPT))
 
291
        dialog.vbox.pack_start(gtk.Label(string))
 
292
        dialog.show_all()
 
293
        result = dialog.run()
 
294
        if result:
 
295
            gtk.main_quit()
 
296
 
 
297
    def success(self):
 
298
        dialog = gtk.Dialog('Successfully built rootfs',
 
299
                self.window,
 
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))
 
303
        dialog.show_all()
 
304
        result = dialog.run()
 
305
        if result:
 
306
            gtk-main_quit()
 
307
 
 
308
    def run_tasksel(self, widget):
 
309
        self.tasks = Popen(["/usr/lib/rootstock/rootstock-tasksel"], stdout=PIPE).communicate()[0].rstrip()
 
310
 
 
311
    def open_profile(self, widget):
 
312
        print 'open'
 
313
 
 
314
    def save_profile(self, widget):
 
315
        print 'save'
 
316
 
 
317
    def destroy(self, widget, data=None):
 
318
        gtk.main_quit()
 
319
 
 
320
    def main(self):
 
321
        gtk.main()
 
322
 
 
323
if __name__ == "__main__":
 
324
    app = MainWin()
 
325
    app.main()