~ubuntu-branches/ubuntu/quantal/testdrive/quantal

« back to all changes in this revision

Viewing changes to testdrive/testdrive.py

  • Committer: Package Import Robot
  • Author(s): Andres Rodriguez, Philip Muškovac, Andres Rodriguez, Robert Ancell
  • Date: 2012-05-15 16:58:37 UTC
  • mfrom: (1.1.46)
  • Revision ID: package-import@ubuntu.com-20120515165837-a8tt6tmn9f31eusg
Tags: 3.16-0ubuntu1
[ Philip Muškovac ]
* Correctly display versions for both -cli and -gtk

[ Andres Rodriguez ]
* testdrive/virt/kvm.py: Generate UUID. (LP: #959308)
* correctly save arch's in preferences (LP: #873235)
* Change tabs to spaces.
* debian/source/format: Added.
* fully migrate to dh_python2

[ Robert Ancell ]
* debian/control:
  - Drop dependency on python-launchpad-integration
* bin/testdrive-gtk:
  - We no longer do Launchpad integration (LP: #999413)

Show diffs side-by-side

added added

removed removed

Lines of Context:
23
23
import xdg.BaseDirectory
24
24
 
25
25
class Testdrive:
26
 
        def __init__(self, pkg_section):
27
 
                self.HOME = os.getenv("HOME", "")
28
 
                self.ISO_URL = os.getenv("ISO_URL", "")
29
 
                self.VIRT = os.getenv("VIRT", "")
30
 
                self.CACHE = os.getenv("CACHE", None)
31
 
                self.CACHE_ISO = os.getenv("CACHE_ISO", None)
32
 
                self.CACHE_IMG = os.getenv("CACHE_IMG", None)
33
 
                self.CLEAN_IMG = os.getenv("CLEAN_IMG", None)
34
 
                self.MEM = os.getenv("MEM", "")
35
 
                self.SMP = os.getenv("SMP", "")
36
 
                self.DISK_FILE = os.getenv("DISK_FILE", "")
37
 
                self.DISK_SIZE = os.getenv("DISK_SIZE", "")
38
 
                self.KVM_ARGS = os.getenv("KVM_ARGS", "")
39
 
                self.VBOX_NAME = os.getenv("VBOX_NAME", "")
40
 
                self.PKG = "testdrive"
41
 
                self.PKGRC = "%src" % self.PKG
42
 
                self.PROTO = None
43
 
                self.ISO_PATH_HEADER = None
44
 
                self.PKG_SECTION = pkg_section
45
 
                self.r = None #Release (maverick, lucid, etc)
46
 
                self.m = None #Arch (amd64, i386)
47
 
                self.f = None #Flavor (ubuntu, kubuntu, etc)
48
 
                self.p = None # Ubuntu ISO Repository (cdimage, releases, cloud-daily, cloud-releases)
49
 
 
50
 
        def set_values(self, var, value):
51
 
                if var == 'kvm_args':
52
 
                        self.KVM_ARGS = value
53
 
                if var == 'mem':
54
 
                        self.MEM = value
55
 
                if var == 'smp':
56
 
                        self.SMP = value
57
 
                if var == 'disk_size':
58
 
                        self.DISK_SIZE = value
59
 
                if var == 'cache':
60
 
                        self.CACHE = value
61
 
                if var == 'cache_img':
62
 
                        self.CACHE_IMG = value
63
 
                if var == 'cache_iso':
64
 
                        self.CACHE_ISO = value
65
 
                if var == 'clean_img':
66
 
                        self.CLEAN_IMG = value
67
 
                if var == 'iso_url':
68
 
                        self.ISO_URL = value
69
 
                if var == 'virt':
70
 
                        self.VIRT = value
71
 
                if var == 'disk_file':
72
 
                        self.DISK_FILE = value
73
 
                if var == 'r':
74
 
                        self.r = value
75
 
                if var == 'm':
76
 
                        self.m = [value]
77
 
                if var == 'f':
78
 
                        self.f = value
79
 
                if var == 'p':
80
 
                        self.p = value
81
 
 
82
 
        def load_config_file(self, config_file):
83
 
                cfg = ConfigParser.ConfigParser()
84
 
                cfg.read(config_file)
85
 
                try:
86
 
                        defaults = cfg.items('testdrive-common')
87
 
                        for items in defaults:
88
 
                                self.set_values(items[0], items[1])
89
 
                except:
90
 
                        pass
91
 
                try:
92
 
                        configitems = cfg.items(self.PKG_SECTION)
93
 
                        for items in configitems:
94
 
                                self.set_values(items[0], items[1])
95
 
                except:
96
 
                        pass
97
 
 
98
 
        ## TODO: This possible needs to go outside the class due to in PyGTK front end we might need the list of ISO's before even instancing an object
99
 
        def list_isos(self, ISOS):
100
 
                ISO = []
101
 
                for iso in ISOS:
102
 
                        if iso.split()[1] == self.r:
103
 
                                # TODO: Add support for Cloud
104
 
                                category = iso.split()[0]
105
 
                                if category == 'ubuntu-server':
106
 
                                        category = 'ubuntu'
107
 
                                elif category == 'ubuntu-netbook':
108
 
                                        category = 'ubuntu'
109
 
                                elif category == 'ubuntu-mobile':
110
 
                                        category = 'ubuntu'
111
 
                                elif category == 'kubuntu-netbook':
112
 
                                        category = 'kubuntu'
113
 
                                elif category == 'kubuntu-mobile':
114
 
                                        category = 'kubuntu'
115
 
                                flavor = iso.split()[0].capitalize()
116
 
                                if flavor == 'Ubuntu-netbook':
117
 
                                        flavor = 'Ubuntu'
118
 
                                elif flavor == 'Ubuntu-mobile':
119
 
                                        flavor == 'Ubuntu'
120
 
                                elif flavor == 'Kubuntu-netbook':
121
 
                                        flavor = 'Kubuntu'
122
 
                                elif flavor == 'Kubuntu-mobile':
123
 
                                        flavor = 'Kubuntu'
124
 
                                elif flavor == 'Ubuntustudio':
125
 
                                        flavor = 'Ubuntu Studio'
126
 
                                elif flavor == 'Ubuntu-server':
127
 
                                        flavor = 'Ubuntu'
128
 
                                elif flavor == 'Cloud-server':
129
 
                                        flavor = 'Cloud Server'
130
 
                                elif flavor == 'Cloud-desktop':
131
 
                                        flavor = 'Cloud Desktop'
132
 
                                release = iso.split()[1]
133
 
                                url = iso.split()[2]
134
 
                                if self.p == 'cloud-daily' or self.p == 'cloud-releases':
135
 
                                        arch = url.split(".tar.gz")[0].split("-")[-1]
136
 
                                        name = "%s" % flavor 
137
 
                                else:
138
 
                                        arch = url.split(".iso")[0].split("-")[-1]
139
 
                                        image = url.split("-%s.iso" % arch)[0].split("-")[-1].capitalize()
140
 
                                        if image == 'Dvd':
141
 
                                                image = url.split("-%s.iso" % arch)[0].split("-")[-1].swapcase()
142
 
                                        name = "%s %s" % (flavor, image)
143
 
                                # Name: Shows a description
144
 
                                # URL: Shows the URL from where it downloads the ISO
145
 
                                # Arch: Shows the architecture (amd64|i386)
146
 
                                # Category: The header used to save the ISO, i.e.: ubuntu_lucid-desktop-i386.iso kubuntu_lucid-desktop-i386.iso
147
 
                                if arch in self.m:
148
 
                                        ISO.append({"name":name, "url":"%s%s" % (self.u, url), "arch":arch, "category":category})
149
 
                return ISO
150
 
 
151
 
        def get_virt(self):
152
 
                acceleration = 0
153
 
                # Check if KVM acceleration can be used
154
 
                if commands.getstatusoutput("which kvm-ok")[0] == 0:
155
 
                        # If we have kvm-ok, let's use it...
156
 
                        if commands.getstatusoutput("kvm-ok")[0] == 0:
157
 
                                acceleration = 1
158
 
                else:
159
 
                        # Okay, we don't have kvm-ok, so let's hack it...
160
 
                        if commands.getstatusoutput("egrep \"^flags.*:.*(svm|vmx)\" /proc/cpuinfo")[0] == 0:
161
 
                                acceleration = 1
162
 
                # Prefer KVM if acceleration available and installed
163
 
                if acceleration == 1 and commands.getstatusoutput("which kvm")[0] == 0:
164
 
                        return "kvm"
165
 
                # Okay, no KVM, VirtualBox maybe?
166
 
                if commands.getstatusoutput("which VBoxManage")[0] == 0:
167
 
                        return "virtualbox"
168
 
                # No VirtualBox, how about Parallels?
169
 
                if commands.getstatusoutput("which prlctl")[0] == 0:
170
 
                        return "parallels"
171
 
                # No hypervisor found; error out with advice
172
 
                if acceleration == 1:
173
 
                        return 1
174
 
                else:
175
 
                        return 0
176
 
 
177
 
        def set_defaults(self):
178
 
                # Set defaults where undefined
179
 
                if self.CACHE is None:
180
 
                        if xdg.BaseDirectory.xdg_cache_home:
181
 
                                self.CACHE = "%s/%s" % (xdg.BaseDirectory.xdg_cache_home, self.PKG)
182
 
                        else:
183
 
                                self.CACHE = "%s/.cache/%s" % (self.HOME, self.PKG)
184
 
 
185
 
                if self.CACHE_IMG is None:
186
 
                        self.CACHE_IMG = '%s/img' % self.CACHE
187
 
                if not os.path.exists(self.CACHE_IMG):
188
 
                        os.makedirs(self.CACHE_IMG, 0700)
189
 
                # if running the image from /dev/shm, remove the image when done
190
 
                # (unless CLEAN_IMG is set)
191
 
                if self.CLEAN_IMG is None:
192
 
                        if self.CACHE_IMG == '/dev/shm':
193
 
                                self.CLEAN_IMG = True
194
 
                        else:
195
 
                                self.CLEAN_IMG = False
196
 
 
197
 
                if self.CACHE_ISO is None:
198
 
                        self.CACHE_ISO = '%s/iso' % self.CACHE
199
 
                if not os.path.exists(self.CACHE_ISO):
200
 
                        os.makedirs(self.CACHE_ISO, 0700)
201
 
 
202
 
                if len(self.SMP) == 0:
203
 
                        self.SMP = commands.getoutput("grep -c ^processor /proc/cpuinfo")
204
 
 
205
 
                if len(self.DISK_SIZE) == 0:
206
 
                        self.DISK_SIZE = "6G"
207
 
 
208
 
                if len(self.MEM) == 0:
209
 
                        total = commands.getoutput("grep ^MemTotal /proc/meminfo | awk '{print $2}'")
210
 
                        if total > 2000000:
211
 
                                self.MEM = "1024"
212
 
                        elif total > 1000000:
213
 
                                self.MEM = "512"
214
 
                        elif total > 750000:
215
 
                                self.MEM = "384"
216
 
                        else:
217
 
                                self.MEM = "256"
218
 
 
219
 
                if len(self.KVM_ARGS) == 0:
220
 
                        self.KVM_ARGS = "-usb -usbdevice tablet -net nic,model=virtio -net user -soundhw es1370"
221
 
 
222
 
                if len(self.VBOX_NAME) == 0:
223
 
                        self.VBOX_NAME = self.PKG
224
 
 
225
 
                if self.ISO_PATH_HEADER == None:
226
 
                        self.ISO_PATH_HEADER = 'other'
227
 
 
228
 
                if self.f == None:
229
 
                        self.f = 'ubuntu'
230
 
 
231
 
                if self.m is None:
232
 
                        if platform.machine() == "x86_64":
233
 
                                self.m = ["amd64", "i386"]
234
 
                        else:
235
 
                                self.m = ["i386"]
236
 
 
237
 
                if self.p == None:
238
 
                        self.p = 'cdimage'
239
 
 
240
 
                if self.p == 'cdimage':
241
 
                        self.u = 'rsync://cdimage.ubuntu.com/cdimage'
242
 
 
243
 
                if self.p == 'releases':
244
 
                        self.u = 'rsync://us.rsync.releases.ubuntu.com/releases'
245
 
 
246
 
                if self.p == 'cloud-daily' or self.p == 'cloud-releases':
247
 
                        self.u = 'rsync://cloud-images.ubuntu.com/cloud-images'
248
 
 
249
 
        def run(self, cmd):
250
 
                return(os.system(cmd))
251
 
 
252
 
        def get_proto(self):
253
 
                if self.PROTO == "rsync":
254
 
                        cmd = "rsync -azPL %s %s" % (self.ISO_URL, self.PATH_TO_ISO)
255
 
                        return cmd
256
 
                elif self.PROTO == "zsync" or self.PROTO == "http" or self.PROTO == "ftp":
257
 
                        if commands.getstatusoutput("which zsync")[0] == 0:
258
 
                                if self.ISO_URL.partition("://")[0] == "zsync":
259
 
                                        self.ISO_URL = self.ISO_URL.replace('zsync', 'http')
260
 
                                cmd = "cd '%s' && zsync %s.zsync -o %s" % (self.CACHE_ISO, self.ISO_URL, self.PATH_TO_ISO)
261
 
                                return cmd
262
 
                        else:
263
 
                                cmd = "wget %s -O %s" % (self.ISO_URL, self.PATH_TO_ISO)
264
 
                                return cmd
265
 
                elif self.PROTO == "file":
266
 
                        # If the iso is on file:///, use the ISO in place
267
 
                        self.PATH_TO_ISO = self.ISO_URL.partition("://")[2]
268
 
                        # Get absolute path if a relative path is used
269
 
                        DIR = commands.getoutput("cd `dirname '%s'` && pwd" % self.PATH_TO_ISO)
270
 
                        FILE = os.path.basename("%s" % self.PATH_TO_ISO)
271
 
                        self.PATH_TO_ISO = "%s/%s" % (DIR, FILE)
272
 
                        return 0
273
 
                else:
274
 
                        #error("Unsupported protocol [%s]" % self.PROTO)
275
 
                        return 1
276
 
 
277
 
        def md5sum(self, file):
278
 
                fh = open(file, 'rb')
279
 
                x = fh.read()
280
 
                fh.close()
281
 
                m = hashlib.md5()
282
 
                m.update(x)
283
 
                return m.hexdigest()
284
 
 
285
 
        def delete_image(self):
286
 
                # if requested to clean out the image mark it to be done
287
 
                if self.CLEAN_IMG:
288
 
                        rm_disk = True
289
 
                else:
290
 
                        rm_disk = False
291
 
 
292
 
                # If disk image is stock (e.g., you just ran a LiveCD, no installation),
293
 
                # purge it automatically.
294
 
                if os.path.exists(self.DISK_FILE):
295
 
                        if os.path.getsize(self.DISK_FILE) == 262144 and self.md5sum(self.DISK_FILE) == "1da7553f642332ec9fb58a6094d2c8ef":
296
 
                                # Clean up kvm qcow2 image
297
 
                                rm_disk = True
298
 
                        if os.path.getsize(self.DISK_FILE) == 24576:
299
 
                                # Clean up vbox image
300
 
                                rm_disk = True
301
 
                        elif os.path.getsize(self.DISK_FILE) == 0:
302
 
                                # Clean up empty file
303
 
                                rm_disk = True
304
 
                        elif self.p == 'cloud-daily' or self.p == 'cloud-releases':
305
 
                                rm_disk = True
306
 
                        if rm_disk:
307
 
                                #info("Cleaning up disk image [%s]..." % DISK_FILE)
308
 
                                os.unlink(self.DISK_FILE)
309
 
                                return True
310
 
                return False
311
 
 
312
 
        def set_launch_path(self):
313
 
                # Move from set_defaults, due to merge of upstream rev 189
314
 
                ISO_NAME = "%s_%s" % (self.ISO_PATH_HEADER, os.path.basename(self.ISO_URL))
315
 
                self.PROTO = self.ISO_URL.partition(":")[0]
316
 
                self.PATH_TO_ISO = "%s/%s" % (self.CACHE_ISO, ISO_NAME)
317
 
 
318
 
        def launch_usb_creator(self):
319
 
                if os.path.exists("/usr/bin/usb-creator-gtk"):
320
 
                        os.execv("/usr/bin/usb-creator-gtk", ["usb-creator-gtk", "-i", self.PATH_TO_ISO])
321
 
                else:
322
 
                        os.execv("/usr/bin/usb-creator-kde", ["usb-creator-kde", "-i", self.PATH_TO_ISO])
323
 
 
324
 
        def is_disk_empty(self):
325
 
                (status, output) = commands.getstatusoutput("file %s | grep -qs 'empty'" % self.DISK_FILE)
326
 
                if status == 0:
327
 
                        return True
328
 
                return False
329
 
 
330
 
        # Obtain available ISO's from Ubuntu cdimage.
331
 
        def is_iso_list_cached(self):
332
 
                if not os.path.exists(self.CACHE):
333
 
                        os.makedirs(self.CACHE, 0700)
334
 
                if not os.path.exists("%s/%s.isos" % (self.CACHE, self.p)):
335
 
                        return False
336
 
                return True
337
 
 
338
 
        def is_iso_list_cache_expired(self):
339
 
                cache_time = time.localtime(os.path.getmtime("%s/%s.isos" % (self.CACHE, self.p)))
340
 
                local_time = time.localtime()
341
 
                time_difference = time.mktime(local_time) - time.mktime(cache_time)
342
 
                # Check for new release at most every 12hrs (60*60*12 = 43200)
343
 
                if time_difference >= 43200:
344
 
                        return True
345
 
                return False
346
 
 
347
 
        def obtain_ubuntu_iso_list_from_repo(self):
348
 
                if self.p == 'cdimage':
349
 
                        (status, output) = commands.getstatusoutput("wget -q -O- http://cdimage.ubuntu.com/.manifest-daily | egrep '(amd64|i386)'")
350
 
                elif self.p == 'releases':
351
 
                        (status, output) = commands.getstatusoutput("wget -q -O- http://releases.ubuntu.com/.manifest | egrep '(amd64|i386)'")
352
 
                elif self.p == 'cloud-daily':
353
 
                        (status, output) = commands.getstatusoutput("wget -q -O- http://cloud-images.ubuntu.com/.manifest-daily | egrep '(amd64|i386)'")
354
 
                elif self.p == 'cloud-releases':
355
 
                        (status, output) = commands.getstatusoutput("wget -q -O- http://cloud-images.ubuntu.com/.manifest | egrep '(amd64|i386)'")
356
 
                return output
357
 
 
358
 
        def update_ubuntu_iso_list_cache(self, str):
359
 
                try:
360
 
                        f = open("%s/%s.isos" % (self.CACHE, self.p),'w')
361
 
                        f.write(str)
362
 
                        f.close
363
 
                except IOError:
364
 
                        pass
365
 
 
366
 
        def get_ubuntu_iso_list(self):
367
 
                try:
368
 
                        f = open("%s/%s.isos" % (self.CACHE, self.p), 'r')
369
 
                        ISO = f.readlines()
370
 
                        f.close
371
 
                except IOError:
372
 
                        pass
373
 
                return ISO
374
 
 
375
 
        def set_ubuntu_release_codename(self, isos):
376
 
                codename = []
377
 
                for iso in isos:
378
 
                        codename.append(iso.split()[1])
379
 
                codename.sort()
380
 
                self.r = codename[-1]
381
 
 
382
 
        def create_disk_file(self):
383
 
                return tempfile.mkstemp(".img", "testdrive-disk-", "%s" % self.CACHE_IMG)[1]
384
 
 
385
 
        def prepare_cloud_img_tarball(self):
386
 
                untar = False
387
 
                TAR_BASENAME = os.path.basename(self.PATH_TO_ISO).split(".tar.gz")[0].split("_")[-1]
388
 
                ORIG_DISK_NAME = "%s.img" % TAR_BASENAME
389
 
                FLOPPY_NAME = "%s-floppy" % TAR_BASENAME
390
 
 
391
 
                image_path = "%s/%s" % (self.CACHE_ISO, ORIG_DISK_NAME)
392
 
                floppy_path = "%s/%s" % (self.CACHE_ISO, FLOPPY_NAME)
393
 
 
394
 
                cmd = 'cd %s && tar Szxvf %s %s %s' % (self.CACHE_ISO, self.PATH_TO_ISO, ORIG_DISK_NAME, FLOPPY_NAME)
395
 
                os.system(cmd)
 
26
    def __init__(self, pkg_section):
 
27
        self.HOME = os.getenv("HOME", "")
 
28
        self.ISO_URL = os.getenv("ISO_URL", "")
 
29
        self.VIRT = os.getenv("VIRT", "")
 
30
        self.CACHE = os.getenv("CACHE", None)
 
31
        self.CACHE_ISO = os.getenv("CACHE_ISO", None)
 
32
        self.CACHE_IMG = os.getenv("CACHE_IMG", None)
 
33
        self.CLEAN_IMG = os.getenv("CLEAN_IMG", None)
 
34
        self.MEM = os.getenv("MEM", "")
 
35
        self.SMP = os.getenv("SMP", "")
 
36
        self.DISK_FILE = os.getenv("DISK_FILE", "")
 
37
        self.DISK_SIZE = os.getenv("DISK_SIZE", "")
 
38
        self.KVM_ARGS = os.getenv("KVM_ARGS", "")
 
39
        self.VBOX_NAME = os.getenv("VBOX_NAME", "")
 
40
        self.PKG = "testdrive"
 
41
        self.PKGRC = "%src" % self.PKG
 
42
        self.PROTO = None
 
43
        self.ISO_PATH_HEADER = None
 
44
        self.PKG_SECTION = pkg_section
 
45
        self.r = None #Release (maverick, lucid, etc)
 
46
        self.m = None #Arch (amd64, i386)
 
47
        self.f = None #Flavor (ubuntu, kubuntu, etc)
 
48
        self.p = None # Ubuntu ISO Repository (cdimage, releases, cloud-daily, cloud-releases)
 
49
 
 
50
    def set_values(self, var, value):
 
51
        if var == 'kvm_args':
 
52
            self.KVM_ARGS = value
 
53
        if var == 'mem':
 
54
            self.MEM = value
 
55
        if var == 'smp':
 
56
            self.SMP = value
 
57
        if var == 'disk_size':
 
58
            self.DISK_SIZE = value
 
59
        if var == 'cache':
 
60
            self.CACHE = value
 
61
        if var == 'cache_img':
 
62
            self.CACHE_IMG = value
 
63
        if var == 'cache_iso':
 
64
            self.CACHE_ISO = value
 
65
        if var == 'clean_img':
 
66
            self.CLEAN_IMG = value
 
67
        if var == 'iso_url':
 
68
            self.ISO_URL = value
 
69
        if var == 'virt':
 
70
            self.VIRT = value
 
71
        if var == 'disk_file':
 
72
            self.DISK_FILE = value
 
73
        if var == 'r':
 
74
            self.r = value
 
75
        if var == 'm':
 
76
            self.m = value.split()
 
77
        if var == 'f':
 
78
            self.f = value
 
79
        if var == 'p':
 
80
            self.p = value
 
81
 
 
82
    def load_config_file(self, config_file):
 
83
        cfg = ConfigParser.ConfigParser()
 
84
        cfg.read(config_file)
 
85
        try:
 
86
            defaults = cfg.items('testdrive-common')
 
87
            for items in defaults:
 
88
                self.set_values(items[0], items[1])
 
89
        except:
 
90
            pass
 
91
        try:
 
92
            configitems = cfg.items(self.PKG_SECTION)
 
93
            for items in configitems:
 
94
                self.set_values(items[0], items[1])
 
95
        except:
 
96
            pass
 
97
 
 
98
    ## TODO: This possible needs to go outside the class due to in PyGTK front end we might need the list of ISO's before even instancing an object
 
99
    def list_isos(self, ISOS):
 
100
        ISO = []
 
101
        for iso in ISOS:
 
102
            if iso.split()[1] == self.r:
 
103
                # TODO: Add support for Cloud
 
104
                category = iso.split()[0]
 
105
                if category == 'ubuntu-server':
 
106
                    category = 'ubuntu'
 
107
                elif category == 'ubuntu-netbook':
 
108
                    category = 'ubuntu'
 
109
                elif category == 'ubuntu-mobile':
 
110
                    category = 'ubuntu'
 
111
                elif category == 'kubuntu-netbook':
 
112
                    category = 'kubuntu'
 
113
                elif category == 'kubuntu-mobile':
 
114
                    category = 'kubuntu'
 
115
                flavor = iso.split()[0].capitalize()
 
116
                if flavor == 'Ubuntu-netbook':
 
117
                    flavor = 'Ubuntu'
 
118
                elif flavor == 'Ubuntu-mobile':
 
119
                    flavor == 'Ubuntu'
 
120
                elif flavor == 'Kubuntu-netbook':
 
121
                    flavor = 'Kubuntu'
 
122
                elif flavor == 'Kubuntu-mobile':
 
123
                    flavor = 'Kubuntu'
 
124
                elif flavor == 'Ubuntustudio':
 
125
                    flavor = 'Ubuntu Studio'
 
126
                elif flavor == 'Ubuntu-server':
 
127
                    flavor = 'Ubuntu'
 
128
                elif flavor == 'Cloud-server':
 
129
                    flavor = 'Cloud Server'
 
130
                elif flavor == 'Cloud-desktop':
 
131
                    flavor = 'Cloud Desktop'
 
132
                release = iso.split()[1]
 
133
                url = iso.split()[2]
 
134
                if self.p == 'cloud-daily' or self.p == 'cloud-releases':
 
135
                    arch = url.split(".tar.gz")[0].split("-")[-1]
 
136
                    name = "%s" % flavor 
 
137
                else:
 
138
                    arch = url.split(".iso")[0].split("-")[-1]
 
139
                    image = url.split("-%s.iso" % arch)[0].split("-")[-1].capitalize()
 
140
                    if image == 'Dvd':
 
141
                        image = url.split("-%s.iso" % arch)[0].split("-")[-1].swapcase()
 
142
                    name = "%s %s" % (flavor, image)
 
143
                # Name: Shows a description
 
144
                # URL: Shows the URL from where it downloads the ISO
 
145
                # Arch: Shows the architecture (amd64|i386)
 
146
                # Category: The header used to save the ISO, i.e.: ubuntu_lucid-desktop-i386.iso kubuntu_lucid-desktop-i386.iso
 
147
                if arch in self.m:
 
148
                    ISO.append({"name":name, "url":"%s%s" % (self.u, url), "arch":arch, "category":category})
 
149
        return ISO
 
150
 
 
151
    def get_virt(self):
 
152
        acceleration = 0
 
153
        # Check if KVM acceleration can be used
 
154
        if commands.getstatusoutput("which kvm-ok")[0] == 0:
 
155
            # If we have kvm-ok, let's use it...
 
156
            if commands.getstatusoutput("kvm-ok")[0] == 0:
 
157
                acceleration = 1
 
158
        else:
 
159
            # Okay, we don't have kvm-ok, so let's hack it...
 
160
            if commands.getstatusoutput("egrep \"^flags.*:.*(svm|vmx)\" /proc/cpuinfo")[0] == 0:
 
161
                acceleration = 1
 
162
        # Prefer KVM if acceleration available and installed
 
163
        if acceleration == 1 and commands.getstatusoutput("which kvm")[0] == 0:
 
164
            return "kvm"
 
165
        # Okay, no KVM, VirtualBox maybe?
 
166
        if commands.getstatusoutput("which VBoxManage")[0] == 0:
 
167
            return "virtualbox"
 
168
        # No VirtualBox, how about Parallels?
 
169
        if commands.getstatusoutput("which prlctl")[0] == 0:
 
170
            return "parallels"
 
171
        # No hypervisor found; error out with advice
 
172
        if acceleration == 1:
 
173
            return 1
 
174
        else:
 
175
            return 0
 
176
 
 
177
    def set_defaults(self):
 
178
        # Set defaults where undefined
 
179
        if self.CACHE is None:
 
180
            if xdg.BaseDirectory.xdg_cache_home:
 
181
                self.CACHE = "%s/%s" % (xdg.BaseDirectory.xdg_cache_home, self.PKG)
 
182
            else:
 
183
                self.CACHE = "%s/.cache/%s" % (self.HOME, self.PKG)
 
184
 
 
185
        if self.CACHE_IMG is None:
 
186
            self.CACHE_IMG = '%s/img' % self.CACHE
 
187
        if not os.path.exists(self.CACHE_IMG):
 
188
            os.makedirs(self.CACHE_IMG, 0700)
 
189
        # if running the image from /dev/shm, remove the image when done
 
190
        # (unless CLEAN_IMG is set)
 
191
        if self.CLEAN_IMG is None:
 
192
            if self.CACHE_IMG == '/dev/shm':
 
193
                self.CLEAN_IMG = True
 
194
            else:
 
195
                self.CLEAN_IMG = False
 
196
 
 
197
        if self.CACHE_ISO is None:
 
198
            self.CACHE_ISO = '%s/iso' % self.CACHE
 
199
        if not os.path.exists(self.CACHE_ISO):
 
200
            os.makedirs(self.CACHE_ISO, 0700)
 
201
 
 
202
        if len(self.SMP) == 0:
 
203
            self.SMP = commands.getoutput("grep -c ^processor /proc/cpuinfo")
 
204
 
 
205
        if len(self.DISK_SIZE) == 0:
 
206
            self.DISK_SIZE = "6G"
 
207
 
 
208
        if len(self.MEM) == 0:
 
209
            total = commands.getoutput("grep ^MemTotal /proc/meminfo | awk '{print $2}'")
 
210
            if total > 2000000:
 
211
                self.MEM = "1024"
 
212
            elif total > 1000000:
 
213
                self.MEM = "512"
 
214
            elif total > 750000:
 
215
                self.MEM = "384"
 
216
            else:
 
217
                self.MEM = "256"
 
218
 
 
219
        if len(self.KVM_ARGS) == 0:
 
220
            self.KVM_ARGS = "-usb -usbdevice tablet -net nic,model=virtio -net user -soundhw es1370"
 
221
 
 
222
        if len(self.VBOX_NAME) == 0:
 
223
            self.VBOX_NAME = self.PKG
 
224
 
 
225
        if self.ISO_PATH_HEADER == None:
 
226
            self.ISO_PATH_HEADER = 'other'
 
227
 
 
228
        if self.f == None:
 
229
            self.f = 'ubuntu'
 
230
 
 
231
        if self.m is None:
 
232
            if platform.machine() == "x86_64":
 
233
                self.m = ["amd64", "i386"]
 
234
            else:
 
235
                self.m = ["i386"]
 
236
 
 
237
        if self.p == None:
 
238
            self.p = 'cdimage'
 
239
 
 
240
        if self.p == 'cdimage':
 
241
            self.u = 'rsync://cdimage.ubuntu.com/cdimage'
 
242
 
 
243
        if self.p == 'releases':
 
244
            self.u = 'rsync://us.rsync.releases.ubuntu.com/releases'
 
245
 
 
246
        if self.p == 'cloud-daily' or self.p == 'cloud-releases':
 
247
            self.u = 'rsync://cloud-images.ubuntu.com/cloud-images'
 
248
 
 
249
    def run(self, cmd):
 
250
        return(os.system(cmd))
 
251
 
 
252
    def get_proto(self):
 
253
        if self.PROTO == "rsync":
 
254
            cmd = "rsync -azPL %s %s" % (self.ISO_URL, self.PATH_TO_ISO)
 
255
            return cmd
 
256
        elif self.PROTO == "zsync" or self.PROTO == "http" or self.PROTO == "ftp":
 
257
            if commands.getstatusoutput("which zsync")[0] == 0:
 
258
                if self.ISO_URL.partition("://")[0] == "zsync":
 
259
                    self.ISO_URL = self.ISO_URL.replace('zsync', 'http')
 
260
                cmd = "cd '%s' && zsync %s.zsync -o %s" % (self.CACHE_ISO, self.ISO_URL, self.PATH_TO_ISO)
 
261
                return cmd
 
262
            else:
 
263
                cmd = "wget %s -O %s" % (self.ISO_URL, self.PATH_TO_ISO)
 
264
                return cmd
 
265
        elif self.PROTO == "file":
 
266
            # If the iso is on file:///, use the ISO in place
 
267
            self.PATH_TO_ISO = self.ISO_URL.partition("://")[2]
 
268
            # Get absolute path if a relative path is used
 
269
            DIR = commands.getoutput("cd `dirname '%s'` && pwd" % self.PATH_TO_ISO)
 
270
            FILE = os.path.basename("%s" % self.PATH_TO_ISO)
 
271
            self.PATH_TO_ISO = "%s/%s" % (DIR, FILE)
 
272
            return 0
 
273
        else:
 
274
            #error("Unsupported protocol [%s]" % self.PROTO)
 
275
            return 1
 
276
 
 
277
    def md5sum(self, file):
 
278
        fh = open(file, 'rb')
 
279
        x = fh.read()
 
280
        fh.close()
 
281
        m = hashlib.md5()
 
282
        m.update(x)
 
283
        return m.hexdigest()
 
284
 
 
285
    def delete_image(self):
 
286
        # if requested to clean out the image mark it to be done
 
287
        if self.CLEAN_IMG:
 
288
            rm_disk = True
 
289
        else:
 
290
            rm_disk = False
 
291
 
 
292
        # If disk image is stock (e.g., you just ran a LiveCD, no installation),
 
293
        # purge it automatically.
 
294
        if os.path.exists(self.DISK_FILE):
 
295
            if os.path.getsize(self.DISK_FILE) == 262144 and self.md5sum(self.DISK_FILE) == "1da7553f642332ec9fb58a6094d2c8ef":
 
296
                # Clean up kvm qcow2 image
 
297
                rm_disk = True
 
298
            if os.path.getsize(self.DISK_FILE) == 24576:
 
299
                # Clean up vbox image
 
300
                rm_disk = True
 
301
            elif os.path.getsize(self.DISK_FILE) == 0:
 
302
                # Clean up empty file
 
303
                rm_disk = True
 
304
            elif self.p == 'cloud-daily' or self.p == 'cloud-releases':
 
305
                rm_disk = True
 
306
            if rm_disk:
 
307
                #info("Cleaning up disk image [%s]..." % DISK_FILE)
 
308
                os.unlink(self.DISK_FILE)
 
309
                return True
 
310
        return False
 
311
 
 
312
    def set_launch_path(self):
 
313
        # Move from set_defaults, due to merge of upstream rev 189
 
314
        ISO_NAME = "%s_%s" % (self.ISO_PATH_HEADER, os.path.basename(self.ISO_URL))
 
315
        self.PROTO = self.ISO_URL.partition(":")[0]
 
316
        self.PATH_TO_ISO = "%s/%s" % (self.CACHE_ISO, ISO_NAME)
 
317
 
 
318
    def launch_usb_creator(self):
 
319
        if os.path.exists("/usr/bin/usb-creator-gtk"):
 
320
            os.execv("/usr/bin/usb-creator-gtk", ["usb-creator-gtk", "-i", self.PATH_TO_ISO])
 
321
        else:
 
322
            os.execv("/usr/bin/usb-creator-kde", ["usb-creator-kde", "-i", self.PATH_TO_ISO])
 
323
 
 
324
    def is_disk_empty(self):
 
325
        (status, output) = commands.getstatusoutput("file %s | grep -qs 'empty'" % self.DISK_FILE)
 
326
        if status == 0:
 
327
            return True
 
328
        return False
 
329
 
 
330
    # Obtain available ISO's from Ubuntu cdimage.
 
331
    def is_iso_list_cached(self):
 
332
        if not os.path.exists(self.CACHE):
 
333
            os.makedirs(self.CACHE, 0700)
 
334
        if not os.path.exists("%s/%s.isos" % (self.CACHE, self.p)):
 
335
            return False
 
336
        return True
 
337
 
 
338
    def is_iso_list_cache_expired(self):
 
339
        cache_time = time.localtime(os.path.getmtime("%s/%s.isos" % (self.CACHE, self.p)))
 
340
        local_time = time.localtime()
 
341
        time_difference = time.mktime(local_time) - time.mktime(cache_time)
 
342
        # Check for new release at most every 12hrs (60*60*12 = 43200)
 
343
        if time_difference >= 43200:
 
344
            return True
 
345
        return False
 
346
 
 
347
    def obtain_ubuntu_iso_list_from_repo(self):
 
348
        if self.p == 'cdimage':
 
349
            (status, output) = commands.getstatusoutput("wget -q -O- http://cdimage.ubuntu.com/.manifest-daily | egrep '(amd64|i386)'")
 
350
        elif self.p == 'releases':
 
351
            (status, output) = commands.getstatusoutput("wget -q -O- http://releases.ubuntu.com/.manifest | egrep '(amd64|i386)'")
 
352
        elif self.p == 'cloud-daily':
 
353
            (status, output) = commands.getstatusoutput("wget -q -O- http://cloud-images.ubuntu.com/.manifest-daily | egrep '(amd64|i386)'")
 
354
        elif self.p == 'cloud-releases':
 
355
            (status, output) = commands.getstatusoutput("wget -q -O- http://cloud-images.ubuntu.com/.manifest | egrep '(amd64|i386)'")
 
356
        return output
 
357
 
 
358
    def update_ubuntu_iso_list_cache(self, str):
 
359
        try:
 
360
            f = open("%s/%s.isos" % (self.CACHE, self.p),'w')
 
361
            f.write(str)
 
362
            f.close
 
363
        except IOError:
 
364
            pass
 
365
 
 
366
    def get_ubuntu_iso_list(self):
 
367
        try:
 
368
            f = open("%s/%s.isos" % (self.CACHE, self.p), 'r')
 
369
            ISO = f.readlines()
 
370
            f.close
 
371
        except IOError:
 
372
            pass
 
373
        return ISO
 
374
 
 
375
    def set_ubuntu_release_codename(self, isos):
 
376
        codename = []
 
377
        for iso in isos:
 
378
            codename.append(iso.split()[1])
 
379
        codename.sort()
 
380
        self.r = codename[-1]
 
381
 
 
382
    def create_disk_file(self):
 
383
        return tempfile.mkstemp(".img", "testdrive-disk-", "%s" % self.CACHE_IMG)[1]
 
384
 
 
385
    def prepare_cloud_img_tarball(self):
 
386
        untar = False
 
387
        TAR_BASENAME = os.path.basename(self.PATH_TO_ISO).split(".tar.gz")[0].split("_")[-1]
 
388
        ORIG_DISK_NAME = "%s.img" % TAR_BASENAME
 
389
        FLOPPY_NAME = "%s-floppy" % TAR_BASENAME
 
390
 
 
391
        image_path = "%s/%s" % (self.CACHE_ISO, ORIG_DISK_NAME)
 
392
        floppy_path = "%s/%s" % (self.CACHE_ISO, FLOPPY_NAME)
 
393
 
 
394
        cmd = 'cd %s && tar Szxvf %s %s %s' % (self.CACHE_ISO, self.PATH_TO_ISO, ORIG_DISK_NAME, FLOPPY_NAME)
 
395
        os.system(cmd)