Merge lp:~psivaa/utah/utah-upgrade2 into lp:~utah/utah/jenkins-upgradetest-setup

Proposed by Para Siva
Status: Merged
Approved by: Max Brustkern
Approved revision: 44
Merged at revision: 25
Proposed branch: lp:~psivaa/utah/utah-upgrade2
Merge into: lp:~utah/utah/jenkins-upgradetest-setup
Diff against target: 893 lines (+763/-2)
22 files modified
jenkins/jenkins.sh (+2/-0)
main/install_main/install_all_main.py (+89/-0)
main/install_main/tc_control (+3/-2)
post-upgrade/README (+8/-0)
post-upgrade/conffiles/tc_control (+9/-0)
post-upgrade/conffiles/test_conffiles.py (+77/-0)
post-upgrade/debconf/debconf_test.py (+68/-0)
post-upgrade/debconf/tc_control (+9/-0)
post-upgrade/debsums/debsums_lite.py (+21/-0)
post-upgrade/debsums/tc_control (+9/-0)
post-upgrade/kernel/tc_control (+11/-0)
post-upgrade/kernel/test_kernel.py (+47/-0)
post-upgrade/lts_upgrade_system/tc_control (+11/-0)
post-upgrade/lts_upgrade_system/test_lts_upgrade_system.py (+73/-0)
post-upgrade/lts_upgrade_user/tc_control (+10/-0)
post-upgrade/lts_upgrade_user/test_lts_upgrade_user.py (+107/-0)
post-upgrade/python_import/tc_control (+10/-0)
post-upgrade/python_import/test_python_import.py (+131/-0)
post-upgrade/tslist.run (+7/-0)
post-upgrade/xserver/tc_control (+9/-0)
post-upgrade/xserver/test_xserver.py (+48/-0)
upgrade.run (+4/-0)
To merge this branch: bzr merge lp:~psivaa/utah/utah-upgrade2
Reviewer Review Type Date Requested Status
Max Brustkern (community) Approve
Para Siva (community) Needs Resubmitting
Review via email: mp+179004@code.launchpad.net

Description of the change

As per the comment in https://code.launchpad.net/~psivaa/utah/utah-upgrade/+merge/177884 and superseding it. Re-basing.
Contains the following changes:
1. Incorporate install_all_main.py rather than using it from the old location with some modification, for ease of maintenance
2. Changed the number of post upgrade tests
3. Added a line to destroy VMs at the end of the test.

To post a comment you must log in.
Revision history for this message
Max Brustkern (nuclearbob) wrote :

Are you cleaning up the disks when destroying the machine?

Revision history for this message
Para Siva (psivaa) wrote :

I am not in favour of cleaning up the disks because that way we could manually restart the VM to investigate the VMs for any information that are not captured from the client logs in case of any failures. Destroying the VMs was introduced to reduce the processor load on the servers.

Revision history for this message
Max Brustkern (nuclearbob) wrote :

I forgot that 'destroy' in libvirt doesn't mean destroy in the way I usually think of it. Keeping them around for that makes sense.

On line 34, should redhat-cluster-suit be redhat-cluster-suite ?

Do the commented lines on 44, 52, 66, 74, and 176 need to stay in?

If it would be useful for the block starting on 629, we can work on doing a display-capable automated test, but I don't think that should hold up this merge.

post-upgrade/ts_control seems unnecessary since everything is commented out, but having it there as a placeholder isn't an unreasonable thing to do.

All of the actual important bits seem reasonable enough to me.

lp:~psivaa/utah/utah-upgrade2 updated
44. By Para Siva

Fixing review comments bar the display-post upgrade test

Revision history for this message
Para Siva (psivaa) :
review: Needs Resubmitting
Revision history for this message
Max Brustkern (nuclearbob) wrote :

Awesome!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'jenkins/jenkins.sh'
2--- jenkins/jenkins.sh 2013-05-31 20:03:27 +0000
3+++ jenkins/jenkins.sh 2013-08-12 10:37:39 +0000
4@@ -92,4 +92,6 @@
5 ${SCP} root@${MACHINE}:/var/log/dist-upgrade/* ${LOG_DIR}/
6 ${SCP} root@${MACHINE}:/var/crash/* ${LOG_DIR}/
7
8+virsh destroy $MACHINE
9+
10 exit $RETCODE
11
12=== added file 'main/install_main/install_all_main.py'
13--- main/install_main/install_all_main.py 1970-01-01 00:00:00 +0000
14+++ main/install_main/install_all_main.py 2013-08-12 10:37:39 +0000
15@@ -0,0 +1,89 @@
16+#!/usr/bin/python3
17+
18+from __future__ import print_function
19+
20+import apt
21+import apt_pkg
22+import platform
23+
24+
25+def blacklisted(name):
26+ # we need to blacklist linux-image-* as it does not install
27+ # cleanly in the chroot (postinst failes)
28+ blacklist = ["libkdc2", "libkdc", "libjpeg", "libgpod", "libapache2",
29+ "libgd", "heimdal", "bacula", "grub", "linux-image-",
30+ "ltsp-client", "glibc-doc-reference", "libpthread-dev",
31+ "cman", "mysql-server", "fuse-utils",
32+ "ltspfs", "gfs2-tools", "edubuntu-server",
33+ "gnbd-client", "gnbd-server", "mysql-server-5.0",
34+ "rgmanager", "clvm", "redhat-cluster-suite",
35+ # has a funny "can not be upgraded automatically" policy
36+ # see debian #368226
37+ "quagga",
38+ "system-config-cluster", "gfs-tools"]
39+ for b in blacklist:
40+ if name.startswith(b):
41+ return True
42+ return False
43+
44+
45+cache = apt.Cache()
46+group = apt_pkg.ActionGroup(cache._depcache)
47+
48+arch = "i386"
49+if platform.machine() == "x86_64":
50+ arch = "amd64"
51+
52+troublemaker = set()
53+for pkg in cache:
54+ if not pkg.candidate and arch not in pkg.fullname:
55+ continue
56+ for c in pkg.candidate.origins:
57+ if c.component == "main":
58+ current = set([p.name for p in cache if p.marked_install])
59+ if (not (pkg.is_installed or blacklisted(pkg.name)) and
60+ arch in pkg.fullname):
61+ pkg.mark_install()
62+ print("Install candidate: %s" % pkg.name)
63+ new = set([p.name for p in cache if p.marked_install])
64+ if not (pkg.is_installed or pkg.marked_install):
65+ print("Can't install: %s" % pkg.name)
66+ if len(current - new) > 0:
67+ troublemaker.add(pkg.name)
68+ print("Installing '%s'\
69+ caused removals_ %s" % (pkg.name, current - new))
70+
71+for pkg in ["ubuntu-desktop", "ubuntu-minimal", "ubuntu-standard"]:
72+ cache[pkg].mark_install()
73+
74+# make sure we don't install blacklisted stuff
75+for pkg in cache:
76+ if blacklisted(pkg.name):
77+ pkg.mark_keep()
78+
79+print("We can install:")
80+print(len([pkg.name for pkg in cache if pkg.marked_install]))
81+print("Download: ")
82+pm = apt_pkg.PackageManager(cache._depcache)
83+fetcher = apt_pkg.Acquire()
84+pm.get_archives(fetcher, cache._list, cache._records)
85+print(apt_pkg.size_to_str(fetcher.fetch_needed))
86+print("Total space: ", apt_pkg.size_to_str(cache._depcache.usr_size))
87+
88+res = False
89+current = 0
90+maxRetries = 3
91+while current < maxRetries:
92+ try:
93+ res = cache.commit(apt.progress.text.AcquireProgress(),
94+ apt.progress.base.InstallProgress())
95+ except IOError as e:
96+ # fetch failed, will be retried
97+ current += 1
98+ print("Retrying to fetch: ", current)
99+ continue
100+ except SystemError as e:
101+ print("Error installing packages! ")
102+ print(e)
103+ print("Install result: ", res)
104+ break
105
106=== modified file 'main/install_main/tc_control'
107--- main/install_main/tc_control 2013-05-31 19:55:55 +0000
108+++ main/install_main/tc_control 2013-08-12 10:37:39 +0000
109@@ -6,5 +6,6 @@
110 1. all packages from main are installed
111 type: userland
112 timeout: 3600 # 10 hours
113-command: ./auto-upgrade-testing/share/scripts/install_all_main
114-tc_setup: bzr branch lp:auto-upgrade-testing
115+command: ./install_all_main.py
116+run_as: root
117+
118
119=== added directory 'post-upgrade'
120=== added file 'post-upgrade/README'
121--- post-upgrade/README 1970-01-01 00:00:00 +0000
122+++ post-upgrade/README 2013-08-12 10:37:39 +0000
123@@ -0,0 +1,8 @@
124+The scripts in this folder are run after the upgrade was performed
125+and after a reboot. They can test various functionality like
126+- is the latest kernel running
127+- is the xserver running
128+- is python still working
129+- are my daemons still running
130+
131+etc
132
133=== added directory 'post-upgrade/conffiles'
134=== added file 'post-upgrade/conffiles/tc_control'
135--- post-upgrade/conffiles/tc_control 1970-01-01 00:00:00 +0000
136+++ post-upgrade/conffiles/tc_control 2013-08-12 10:37:39 +0000
137@@ -0,0 +1,9 @@
138+description: Check if there are obsolete conf files left over after upgrade
139+dependencies: none
140+action: |
141+ 1. Test if there are obsolete config files left after the upgrade
142+expected_results: |
143+ 1. No obsolete conf files left afte the upgrade
144+type: userland
145+timeout: 60 # 1 minute
146+command: ./test_conffiles.py
147
148=== added file 'post-upgrade/conffiles/test_conffiles.py'
149--- post-upgrade/conffiles/test_conffiles.py 1970-01-01 00:00:00 +0000
150+++ post-upgrade/conffiles/test_conffiles.py 2013-08-12 10:37:39 +0000
151@@ -0,0 +1,77 @@
152+#!/usr/bin/python
153+#
154+# This script checks status of configuration files after upgrade.
155+# Current checks are:
156+# - Obsolete config files
157+# - Existence of *.dpkg-dist files. It means there was a prompt for an
158+# unmodified configuration during upgrade
159+#
160+# (C) 2012 Canonical Ltd.
161+# Author: Jean-Baptiste Lallement <jean-baptiste.lallement@canonical.com>
162+# License: GPL v2 or higher
163+
164+import unittest
165+import subprocess
166+import glob
167+
168+class TestConfFiles(unittest.TestCase):
169+ def test_obsolete_configfile(self):
170+ '''Check for obsolete config files after upgrade'''
171+ cmd = ['dpkg-query' ,'-W', '-f=${Package}\n${Conffiles}\n\n']
172+ output_file = '/tmp/obsolete_conffiles.log'
173+ test_output = ''
174+
175+ dpkgquery = subprocess.check_output(cmd)
176+ current = set()
177+ obsolete = {}
178+ for pkg in dpkgquery.split('\n\n'):
179+ pkg = pkg.strip().split('\n')
180+ pkgname = pkg[0]
181+ cfgfiles = pkg[1:]
182+ for cfgfile in cfgfiles:
183+ cfgbits = cfgfile.strip().split()
184+ if len(cfgbits) < 3:
185+ # No status, not obsolete
186+ current.add(cfgbits[0])
187+ else:
188+ file, md5, status = cfgbits[:3]
189+ if 'obsolete' in status:
190+ obsolete.setdefault(pkgname, []).append(file)
191+ else:
192+ current.add(file)
193+
194+ for pkgname in sorted(obsolete.keys()):
195+ cfgfiles = [cfgfile for cfgfile in obsolete[pkgname]
196+ if cfgfile not in current]
197+ if cfgfiles:
198+ test_output += "%s\n %s\n" % (pkgname, "\n ".join(cfgfiles))
199+
200+ if test_output:
201+ with open(output_file, 'w') as f:
202+ print >>f, test_output
203+
204+ def test_dpkgdist(self):
205+ '''Check for existence of *.dpkg-dist files'''
206+ whitelist_dpkg = [
207+ '/tmp/sudoers.dpkg-dist',
208+ '/tmp/release-upgrades.dpkg-dist']
209+
210+ dpkgdist_files = subprocess.check_output(['find', '/etc', '-name', \
211+ '*.dpkg-dist']).split('\n')
212+ for f in dpkgdist_files:
213+ if f.strip():
214+ subprocess.check_call(['cp %s /tmp/' % f], shell=True)
215+ conffile = f.replace('.dpkg-dist', '')
216+ subprocess.check_call(['cp %s /tmp/' % conffile], shell=True)
217+
218+ saved_dpkgdist_files = glob.glob('/tmp/*.dpkg-dist')
219+ saved_dpkgdist_files = [f for f in saved_dpkgdist_files \
220+ if f not in whitelist_dpkg]
221+
222+ self.assertEqual(
223+ len(saved_dpkgdist_files), 0,
224+ "*.dpkg-dist files found after upgrade:\n %s" %
225+ "\n ".join(saved_dpkgdist_files))
226+
227+if __name__ == '__main__':
228+ unittest.main()
229
230=== added directory 'post-upgrade/debconf'
231=== added file 'post-upgrade/debconf/debconf_test.py'
232--- post-upgrade/debconf/debconf_test.py 1970-01-01 00:00:00 +0000
233+++ post-upgrade/debconf/debconf_test.py 2013-08-12 10:37:39 +0000
234@@ -0,0 +1,68 @@
235+#!/usr/bin/python
236+"""
237+Parse debconf log file and split in a file per prompt
238+Exit with status 1 if there is a debconf prompt not in whitelist
239+"""
240+from __future__ import print_function
241+
242+import re, os, sys
243+
244+# Keep this path in sync with the corresponding setting in
245+# profile/defaults.cfg.d/defaults.cfg
246+DEBCONF_LOG_PATH = '/var/log/dist-upgrade/debconf.log'
247+RESULT_DIR = '/tmp'
248+
249+# Prompts in this list won't generate a test failure
250+# i.e WHITELIST = ['libraries/restart-without-asking']
251+WHITELIST = [
252+ 'glibc/restart-services',
253+ 'libraries/restart-without-asking' ]
254+
255+def run_test(logfile, resultdir):
256+ """ Run the test and slice debconf log
257+
258+ :param logfile: Path to debconf log
259+ :param resultdir: Output directory to write log file to
260+ """
261+ global WHITELIST
262+
263+ ret = 0
264+ if not os.path.exists(logfile):
265+ print('Debconf logfile not present. Whitelist. Skipping!')
266+ return ret
267+
268+ re_dsetting = re.compile('^\w')
269+ inprompt = False
270+ prompt = dsetting = ""
271+
272+ with open(logfile, 'r') as f_in:
273+ for line in f_in.readlines():
274+ # Only keep interesting bits of the prompt
275+ if line.startswith('#####'):
276+ inprompt = not inprompt
277+
278+ # Reached the second separator, write content to result file
279+ # One per prompt
280+ if not inprompt:
281+ print("Got debconf prompt for '%s'" % dsetting)
282+ if dsetting in WHITELIST:
283+ print(' But it is in Whitelist. Skipping!')
284+ continue
285+ else:
286+ ret = 1
287+
288+ with open(os.path.join(
289+ resultdir,
290+ 'debconf_%s.log' % dsetting.replace('/', '_')),
291+ 'w') as f_out:
292+ f_out.write(prompt)
293+
294+ if inprompt:
295+ prompt += line
296+ if re_dsetting.match(line) and '=' in line:
297+ dsetting = line.split('=')[0]
298+
299+ return ret
300+
301+if __name__ == '__main__':
302+ sys.exit(run_test(DEBCONF_LOG_PATH, RESULT_DIR))
303
304=== added file 'post-upgrade/debconf/tc_control'
305--- post-upgrade/debconf/tc_control 1970-01-01 00:00:00 +0000
306+++ post-upgrade/debconf/tc_control 2013-08-12 10:37:39 +0000
307@@ -0,0 +1,9 @@
308+description: Check if there is any unnecessary prompts during upgrade
309+dependencies: none
310+action: |
311+ 1. Test there is no unnecessary user prompts during the upgrade
312+expected_results: |
313+ 1. There is no prompts unless user modified the files beforehand.
314+type: userland
315+timeout: 60 # 1 minute
316+command: ./debconf_test.py
317
318=== added directory 'post-upgrade/debsums'
319=== added file 'post-upgrade/debsums/debsums_lite.py'
320--- post-upgrade/debsums/debsums_lite.py 1970-01-01 00:00:00 +0000
321+++ post-upgrade/debsums/debsums_lite.py 2013-08-12 10:37:39 +0000
322@@ -0,0 +1,21 @@
323+#!/usr/bin/python
324+
325+from __future__ import print_function
326+
327+import glob
328+import os
329+import subprocess
330+import sys
331+
332+basepath = "/var/lib/dpkg/info/*.md5sums"
333+ok = True
334+for f in glob.glob(basepath):
335+ ret = subprocess.call(["md5sum", "--quiet", "-c",
336+ os.path.join(basepath, f)],
337+ cwd="/")
338+ if ret != 0:
339+ ok = False
340+
341+if not ok:
342+ print("WARNING: at least one md5sum mismatch")
343+ sys.exit(1)
344
345=== added file 'post-upgrade/debsums/tc_control'
346--- post-upgrade/debsums/tc_control 1970-01-01 00:00:00 +0000
347+++ post-upgrade/debsums/tc_control 2013-08-12 10:37:39 +0000
348@@ -0,0 +1,9 @@
349+description: Check for package debsum mismatches
350+dependencies: none
351+action: |
352+ 1. Check if the md5sums of the installed packages match their debsums
353+expected_results: |
354+ 1. The debsums of the packages match
355+type: userland
356+timeout: 60 # 1 minute
357+command: ./debsums_lite.py
358
359=== added directory 'post-upgrade/kernel'
360=== added file 'post-upgrade/kernel/tc_control'
361--- post-upgrade/kernel/tc_control 1970-01-01 00:00:00 +0000
362+++ post-upgrade/kernel/tc_control 2013-08-12 10:37:39 +0000
363@@ -0,0 +1,11 @@
364+description: Check if the kernel update was proper during the upgrade
365+dependencies: none
366+action: |
367+ 1. Test if the kernel being used after the ugprade and reboot is the latest
368+ 2. Test if there are at-least two kernels installed (old and new)
369+expected_results: |
370+ 1. The kernel in use is the new kernel that was installed during the upgrade
371+ 2. At least two kernel versions are in the system
372+type: userland
373+timeout: 60 # 1 minute
374+command: ./test_kernel.py
375
376=== added file 'post-upgrade/kernel/test_kernel.py'
377--- post-upgrade/kernel/test_kernel.py 1970-01-01 00:00:00 +0000
378+++ post-upgrade/kernel/test_kernel.py 2013-08-12 10:37:39 +0000
379@@ -0,0 +1,47 @@
380+#!/usr/bin/python
381+#
382+# This script checks for that at least 2 kernels are installed post-upgrade
383+# and that the latest one is active
384+#
385+# (C) 2012 Canonical Ltd.
386+# Author: Jean-Baptiste Lallement <jean-baptiste.lallement@canonical.com>
387+# Based on the original version from Michael Vogt
388+# License: GPL v2 or higher
389+
390+import unittest
391+import apt_pkg
392+import glob
393+import os
394+
395+class TestKernel(unittest.TestCase):
396+ def setUp(self):
397+ apt_pkg.init()
398+ self.current_kernelversion = os.uname()[2]
399+ self.versions = set()
400+ for kernel in glob.glob('/boot/vmlinuz-*'):
401+ version = "-".join(kernel.split("-")[1:4])
402+ self.versions.add(version)
403+
404+ def test_kernel_in_use(self):
405+ '''Check latest kernel is in use'''
406+ if os.path.exists("/run/container_type"):
407+ with open("/run/container_type") as fd:
408+ container = fd.read().strip()
409+ print("Skipping test_kernel_in_use as in a '%s' container." % container)
410+ return
411+
412+ for version in self.versions:
413+ self.assertFalse(
414+ apt_pkg.version_compare(self.current_kernelversion, version) < 0,
415+ "There is a kernel version '%s' installed higher than the running kernel '%s'" %
416+ (version, self.current_kernelversion))
417+
418+ def test_old_kernel_is_installed(self):
419+ '''Check that previous kernel is still there after install'''
420+ self.assertNotEqual(
421+ len(self.versions), 1,
422+ "Only one kernel found '%s', expected at least 2 (new + previous)" %
423+ self.versions)
424+
425+if __name__ == '__main__':
426+ unittest.main()
427
428=== added directory 'post-upgrade/lts_upgrade_system'
429=== added file 'post-upgrade/lts_upgrade_system/tc_control'
430--- post-upgrade/lts_upgrade_system/tc_control 1970-01-01 00:00:00 +0000
431+++ post-upgrade/lts_upgrade_system/tc_control 2013-08-12 10:37:39 +0000
432@@ -0,0 +1,11 @@
433+description: Check if system config settings are preserved
434+dependencies: none
435+action: |
436+ 1. Check if system wide configuration customisation is preserved
437+ for an lts->lts upgrade. Skipped for anything else
438+expected_results: |
439+ 1. System wide configuration customisation is preserved for lts->lts
440+ upgrades
441+type: userland
442+timeout: 60 # 1 minute
443+command: ./test_lts_upgrade_system.py
444
445=== added file 'post-upgrade/lts_upgrade_system/test_lts_upgrade_system.py'
446--- post-upgrade/lts_upgrade_system/test_lts_upgrade_system.py 1970-01-01 00:00:00 +0000
447+++ post-upgrade/lts_upgrade_system/test_lts_upgrade_system.py 2013-08-12 10:37:39 +0000
448@@ -0,0 +1,73 @@
449+#!/usr/bin/python
450+#
451+# This script checks system-wide configuration settings after an Ubuntu 10.04
452+# LTS to Ubuntu 12.04 LTS upgrade. Run this after upgrading to 12.04 or later.
453+# It reads the old gdm settings and ensures that they were appropriately
454+# migrated to lightdm and that lightdm is the default DM.
455+# It does not need any particular privileges, it is fine to run this as any
456+# user.
457+#
458+# (C) 2012 Canonical Ltd.
459+# Author: Martin Pitt <martin.pitt@ubuntu.com>
460+# License: GPL v2 or higher
461+
462+from __future__ import print_function
463+
464+import unittest
465+import os, sys
466+try:
467+ import configparser
468+ configparser # pyflakes
469+except ImportError:
470+ import ConfigParser as configparser
471+
472+class T(unittest.TestCase):
473+ @classmethod
474+ def setUpClass(klass):
475+ # read gdm configuration
476+ klass.gdm_config = klass._read_conf('/etc/gdm/custom.conf', 'daemon')
477+ klass.lightdm_config = klass._read_conf('/etc/lightdm/lightdm.conf', 'SeatDefaults')
478+
479+ def test_lightdm_default_dm(self):
480+ '''lightdm is the default display manager'''
481+
482+ with open('/etc/X11/default-display-manager') as f:
483+ default_dm = f.read().strip()
484+
485+ self.assertTrue(os.access(default_dm, os.X_OK))
486+ self.assertEqual(os.path.basename(default_dm), 'lightdm')
487+
488+ def test_autologin_migration(self):
489+ '''autologin migration from gdm to lightdm'''
490+
491+ if self.gdm_config.get('automaticloginenable', 'false') == 'true':
492+ gdm_autologin = self.gdm_config.get('automaticlogin', '')
493+ else:
494+ gdm_autologin = ''
495+
496+ self.assertEqual(gdm_autologin, self.lightdm_config.get('autologin-user', ''))
497+
498+ @classmethod
499+ def _read_conf(klass, filename, section):
500+ '''Read section from an INI configuration file.
501+
502+ Return a dictionary with the configuration of the given section.
503+ '''
504+ p = configparser.ConfigParser()
505+ p.read(filename)
506+ config = {}
507+ try:
508+ for (key, value) in p.items(section):
509+ config[key] = value
510+ except configparser.NoSectionError:
511+ # just keep an empty config
512+ pass
513+ return config
514+
515+# Only run on lts-ubuntu testcases
516+if not os.path.exists('/upgrade-tester/prepare_lts_desktop'):
517+ print("Not an Ubuntu Desktop LTS upgrade. Skipping!")
518+ sys.exit(0)
519+
520+if __name__ == '__main__':
521+ unittest.main()
522
523=== added directory 'post-upgrade/lts_upgrade_user'
524=== added file 'post-upgrade/lts_upgrade_user/tc_control'
525--- post-upgrade/lts_upgrade_user/tc_control 1970-01-01 00:00:00 +0000
526+++ post-upgrade/lts_upgrade_user/tc_control 2013-08-12 10:37:39 +0000
527@@ -0,0 +1,10 @@
528+description: Check if user config settings are preserved for lts upgrade
529+dependencies: none
530+action: |
531+ 1. Check if the user config settings are preserved
532+ after an lts->lts upgrade. Skipped for anything else
533+expected_results: |
534+ 1. User config settings are preserved for an lts->lts upgrade
535+type: userland
536+timeout: 60 # 1 minute
537+command: ./test_lts_upgrade_user.py
538
539=== added file 'post-upgrade/lts_upgrade_user/test_lts_upgrade_user.py'
540--- post-upgrade/lts_upgrade_user/test_lts_upgrade_user.py 1970-01-01 00:00:00 +0000
541+++ post-upgrade/lts_upgrade_user/test_lts_upgrade_user.py 2013-08-12 10:37:39 +0000
542@@ -0,0 +1,107 @@
543+#!/usr/bin/python
544+#
545+# This script checks user configuration settings after an Ubuntu 10.04
546+# LTS to Ubuntu 12.04 LTS upgrade. Run prepare_lts_upgrade_user.sh in 10.04
547+# LTS, then upgrade to 12.04 LTS (or later), and run this script to confirm
548+# that settings were migrated properly. In particular this checks for gconf ->
549+# gsettings migration (and sometimes changing the format of the values) for
550+# popular settings, as well as custom panel/desktop launchers.
551+#
552+# You need to run both the prepare and this test script as the same user,
553+# in a full desktop session.
554+#
555+# (C) 2012 Canonical Ltd.
556+# Author: Martin Pitt <martin.pitt@ubuntu.com>
557+# License: GPL v2 or higher
558+
559+from __future__ import print_function
560+
561+import unittest
562+import os, sys
563+import subprocess
564+from time import sleep
565+
566+try:
567+ from gi.repository import Gio
568+except:
569+ # Not a desktop
570+ print("Failed to import gi.repository. Not a LTS Desktop Upgrade. Skipping!")
571+ sys.exit(0)
572+
573+class T(unittest.TestCase):
574+ def test_background(self):
575+ '''background image'''
576+
577+ bg_settings = Gio.Settings('org.gnome.desktop.background')
578+ # note: original gconf value does not have a file:// prefix, but GNOME
579+ # 3.x requires this prefix
580+ self.assertEqual(bg_settings.get_string('picture-uri'),
581+ 'file://%s/mybackground.jpg' % os.environ['HOME'])
582+
583+# Theme is not preserved on upgrade. LP: #969569
584+# Test disabled
585+# def test_gtk_theme(self):
586+# '''GTK theme'''
587+#
588+# iface_settings = Gio.Settings('org.gnome.desktop.interface')
589+# self.assertEqual(iface_settings.get_string('gtk-theme'), 'Radiance')
590+
591+ def test_custom_launchers(self):
592+ '''Custom panel/desktop launchers appear in Unity launcher'''
593+
594+ launcher_settings = Gio.Settings('com.canonical.Unity.Launcher')
595+ favorites = launcher_settings['favorites']
596+
597+ # gedit was dragged from Application menu to panel, pointing to system
598+ # .desktop file
599+ self.assertTrue('gedit.desktop' in favorites)
600+
601+ # custom "echo hello" panel starter uses its own .desktop file
602+ for starter in favorites:
603+ if 'echo' in starter:
604+ self.assertTrue(os.path.exists(starter))
605+ break
606+ else:
607+ self.fail('custom hello starter not found')
608+
609+ # gucharmap was dragged from Application menu to desktop, should be
610+ # converted to system .desktop file
611+ self.assertTrue('gucharmap.desktop' in favorites)
612+
613+ # custom "bc -l" desktop starter uses its own .desktop file
614+ self.assertTrue('%s/Desktop/termcalc.desktop' % os.environ['HOME'] in favorites)
615+
616+ def test_keyboard_layouts(self):
617+ '''Custom keyboard layouts are migrated and applied'''
618+
619+ # verify gconf->gsettings migration
620+ kbd_settings = Gio.Settings('org.gnome.libgnomekbd.keyboard')
621+ self.assertEqual(kbd_settings['layouts'],
622+ ['us','de\tnodeadkeys','gb','gb\tdvorak'])
623+
624+# NO DISPLAY IN AUTOMATED TEST
625+# # verify that they get applied to the X server correctly
626+# xprop = subprocess.Popen(['xprop', '-root', '_XKB_RULES_NAMES'],
627+# stdout=subprocess.PIPE, universal_newlines=True)
628+# out = xprop.communicate()[0]
629+# self.assertEqual(xprop.returncode, 0)
630+#
631+# # chop off key name
632+# out = out.split('=', 1)[1].strip()
633+#
634+# self.assertEqual(out, '"evdev", "pc105", "us,de,gb,gb", ",nodeadkeys,,dvorak", "grp:alts_toggle"')
635+
636+# Only run on lts-ubuntu testcases
637+if not os.path.exists('/upgrade-tester/prepare_lts_desktop'):
638+ print("Not an Ubuntu Desktop LTS upgrade. Skipping!")
639+ sys.exit(0)
640+
641+if os.getuid() == 0:
642+ # Root ? reexecute itself as user ubuntu
643+ ret = subprocess.call('sudo -H -u ubuntu dbus-launch %s' %
644+ os.path.abspath(__file__), shell=True)
645+ sys.exit(ret)
646+else:
647+ # Give 1 minute for the session to start, convert, ...
648+ sleep(60)
649+ unittest.main()
650
651=== added directory 'post-upgrade/python_import'
652=== added file 'post-upgrade/python_import/tc_control'
653--- post-upgrade/python_import/tc_control 1970-01-01 00:00:00 +0000
654+++ post-upgrade/python_import/tc_control 2013-08-12 10:37:39 +0000
655@@ -0,0 +1,10 @@
656+description: Check if python modules are importable
657+dependencies: none
658+action: |
659+ 1. Attempt to import the py modules listed under dist-packages
660+ of the default version
661+expected_results: |
662+ 1. The modules present in dist-packages are importable
663+type: userland
664+timeout: 60 # 1 minute
665+command: ./test_python_import.py
666
667=== added file 'post-upgrade/python_import/test_python_import.py'
668--- post-upgrade/python_import/test_python_import.py 1970-01-01 00:00:00 +0000
669+++ post-upgrade/python_import/test_python_import.py 2013-08-12 10:37:39 +0000
670@@ -0,0 +1,131 @@
671+#!/usr/bin/python
672+#
673+# This script checks python. Current tests:
674+# - import python modules available on the systen
675+#
676+# (C) 2012 Canonical Ltd.
677+# Author: Jean-Baptiste Lallement <jean-baptiste.lallement@canonical.com>
678+# Based on original version from Michael Vogt
679+# License: GPL v2 or higher
680+
681+import unittest
682+import ConfigParser
683+import os
684+import logging
685+import subprocess
686+
687+logging.basicConfig(
688+ filename='/tmp/%s.log' % os.path.basename(__file__)[:-3],
689+ filemode='w',
690+ level=logging.DEBUG)
691+
692+# stuff that we know does not work when doing a simple "import"
693+BLACKLIST = ["speechd_config",
694+ "PAMmodule.so",
695+ "aomodule.so",
696+ "plannerui.so",
697+ "desktopcouch", # needs a KeyringDaemon
698+ "ropemacs", # just hangs
699+ "keyring", # needs X
700+ "invest",
701+ "Onboard",
702+ "goocanvasmodule.so",
703+ ]
704+
705+# If you want to test modules that require a display you'll have to install
706+# xvfb in the base image
707+XVFB_BIN='/usr/bin/xvfb-run'
708+XVFB_OPT=[]
709+
710+def py_module_filter(pymodule):
711+ return not (
712+ pymodule.endswith(".egg-info") or
713+ pymodule.endswith(".pth") or
714+ pymodule.startswith("_") or
715+ pymodule.endswith(".pyc") or
716+ pymodule.endswith("_d.so") or
717+ pymodule in BLACKLIST
718+ )
719+
720+def get_module_from_path(path):
721+ f = os.path.basename(path)
722+ if path and os.path.exists(os.path.join(path, "__init__.py")):
723+ return f
724+ elif f.endswith(".py"):
725+ return f.split(".")[0]
726+ # swig uses this, calls it "foomodule.so" but the import is "foo"
727+ # (eg xdelta3module.so, pqueuemodule.so)
728+ elif f.endswith("module.so"):
729+ return f.split("modules.so")[0]
730+ elif f.endswith(".so"):
731+ return f.split(".")[0]
732+
733+class TestPython(unittest.TestCase):
734+ # total imports
735+ total = 0
736+ failed = []
737+
738+ def _try_import(self, path):
739+ '''Try to import a module from a path
740+
741+ a simple __import__(module) does not work, the problem
742+ is that module import have funny side-effects (like
743+ "import uno; import pyatspi" will fail, but importing
744+ them individually is fine
745+ '''
746+ logging.info('Importing %s', path)
747+ module = get_module_from_path(path)
748+ rc = True
749+ if not module:
750+ logging.warn("could not get module for '%s'" % path)
751+ return rc
752+
753+ try:
754+ cmd = ["python", "-c","import %s" % module]
755+ self.total += 1
756+ subprocess.check_call(cmd, stderr = self.stderr)
757+ except subprocess.CalledProcessError:
758+ try:
759+ pkg = subprocess.check_output(["dpkg", "-S", os.path.realpath(path)])
760+ self.failed.append((module, pkg.strip()))
761+ logging.error('Import failed. Package providing this module: %s', pkg)
762+ except subprocess.CalledProcessError:
763+ logging.error("Import of %s failed, and no package ships this module.", path)
764+ rc = False
765+ return rc
766+
767+ def setUp(self):
768+ # Read default python version installed on the system
769+ config = ConfigParser.SafeConfigParser()
770+ config.read('/usr/share/python/debian_defaults')
771+ self.default_version = config.get('DEFAULT', 'default-version')
772+ self.distpackages = '/usr/lib/%s/dist-packages/' % self.default_version
773+ self.stderr = open('/tmp/%s.stderr' % os.path.basename(__file__)[:-3],'w')
774+
775+ def tearDown(self):
776+ self.stderr.close()
777+
778+ def test_python_import(self):
779+ '''Import python modules from /usr/lib/PYTHONVER/dist-packages/'''
780+ res = True
781+
782+ for module in filter(py_module_filter, os.listdir(self.distpackages)):
783+ res &= self._try_import(os.path.join(self.distpackages, module))
784+
785+ logging.info('Modules imported: %d', self.total)
786+ if res:
787+ logging.info('No failure')
788+
789+ self.assertTrue(res, '%d module(s) failed to import' % len(self.failed))
790+
791+if __name__ == '__main__':
792+ if 'DISPLAY' in os.environ:
793+ unittest.main()
794+ elif os.path.exists(XVFB_BIN):
795+ logging.info("'%s' found and DISPLAY not set. Re-executing myself with xvfb")
796+ cmd = [ XVFB_BIN ] + XVFB_OPT + [os.path.abspath(__file__)]
797+ logging.info(cmd)
798+ subprocess.call(cmd)
799+ else:
800+ logging.warning("'%s' not found and DISPLAY not set. Executing test without a display", XVFB_BIN)
801+ unittest.main()
802
803=== added file 'post-upgrade/tslist.run'
804--- post-upgrade/tslist.run 1970-01-01 00:00:00 +0000
805+++ post-upgrade/tslist.run 2013-08-12 10:37:39 +0000
806@@ -0,0 +1,7 @@
807+- test: conffiles
808+- test: debconf
809+- test: kernel
810+- test: lts_upgrade_system
811+- test: lts_upgrade_user
812+- test: python_import
813+- test: xserver
814
815=== added directory 'post-upgrade/xserver'
816=== added file 'post-upgrade/xserver/tc_control'
817--- post-upgrade/xserver/tc_control 1970-01-01 00:00:00 +0000
818+++ post-upgrade/xserver/tc_control 2013-08-12 10:37:39 +0000
819@@ -0,0 +1,9 @@
820+description: Checking for Xorg after upgrade
821+dependencies: none
822+action: |
823+ 1. Check if Xorg is running for desktop upgrades. Skip the test for others
824+expected_results: |
825+ 1. For desktop upgrades Xorg is running
826+type: userland
827+timeout: 60 # 1 minute
828+command: ./test_xserver.py
829
830=== added file 'post-upgrade/xserver/test_xserver.py'
831--- post-upgrade/xserver/test_xserver.py 1970-01-01 00:00:00 +0000
832+++ post-upgrade/xserver/test_xserver.py 2013-08-12 10:37:39 +0000
833@@ -0,0 +1,48 @@
834+#!/usr/bin/python
835+#
836+# This script checks that xserver is running
837+#
838+# (C) 2012 Canonical Ltd.
839+# Author: Jean-Baptiste Lallement <jean-baptiste.lallement@canonical.com>
840+# Based on the original version from Michael Vogt
841+# License: GPL v2 or higher
842+
843+import unittest
844+import subprocess
845+from time import sleep
846+
847+def is_process_running(procname):
848+ '''Check if a process is running'''
849+ proclist = subprocess.Popen(["ps","-eo","comm"], stdout=subprocess.PIPE,
850+ universal_newlines=True).communicate()[0]
851+ for line in proclist.split("\n"):
852+ if line == procname:
853+ return True
854+ return False
855+
856+def is_desktop_install():
857+ '''Check that at least an *ubuntu-desktop package is installed'''
858+ cmd = ['dpkg-query', '-Wf', '${Status}\n', '*ubuntu-desktop']
859+ try:
860+ output = subprocess.check_output(cmd).split('\n')
861+ except:
862+ return False
863+
864+ for line in output:
865+ if line.startswith('install'):
866+ return True
867+ return False
868+
869+class TestXserver(unittest.TestCase):
870+ @unittest.skipIf(not is_desktop_install(), 'Not a desktop installation.')
871+ def test_xserver_running(self):
872+ '''Checking for running Xorg'''
873+ count = 0
874+ while not is_process_running('Xorg') and count<10:
875+ count += 1
876+ sleep(10)
877+
878+ self.assertTrue(is_process_running('Xorg'), 'X Server not running')
879+
880+if __name__ == '__main__':
881+ unittest.main()
882
883=== modified file 'upgrade.run'
884--- upgrade.run 2013-05-30 21:11:38 +0000
885+++ upgrade.run 2013-08-12 10:37:39 +0000
886@@ -3,3 +3,7 @@
887 - name: upgrade
888 fetch_method: bzr-export
889 fetch_location: lp:~utah/utah/jenkins-upgradetest-setup/upgrade
890+
891+ - name: post-upgrade
892+ fetch_method: bzr-export
893+ fetch_location: lp:~utah/utah/jenkins-upgradetest-setup/post-upgrade

Subscribers

People subscribed via source and target branches

to all changes: