auto-upgrade-testing/0000775000000000000000000000000012076525005012020 5ustar auto-upgrade-testing/share/0000775000000000000000000000000012076525005013122 5ustar auto-upgrade-testing/share/toChroot/0000775000000000000000000000000012076525005014723 5ustar auto-upgrade-testing/share/toChroot/etc/0000775000000000000000000000000012076525005015476 5ustar auto-upgrade-testing/share/toChroot/etc/kernel-img.conf0000664000000000000000000000016012076525005020374 0ustar do_symlinks = yes relative_links = yes do_bootloader = no do_bootfloppy = no do_initrd = yes link_in_boot = yes auto-upgrade-testing/share/toChroot/etc/hosts0000664000000000000000000000005312076525005016557 0ustar 127.0.0.1 localhost.localdomain localhost auto-upgrade-testing/share/post_upgrade_tests/0000775000000000000000000000000012076525005017040 5ustar auto-upgrade-testing/share/post_upgrade_tests/test_lts_upgrade_user.py0000775000000000000000000000760212076525005024030 0ustar #!/usr/bin/python # # This script checks user configuration settings after an Ubuntu 10.04 # LTS to Ubuntu 12.04 LTS upgrade. Run prepare_lts_upgrade_user.sh in 10.04 # LTS, then upgrade to 12.04 LTS (or later), and run this script to confirm # that settings were migrated properly. In particular this checks for gconf -> # gsettings migration (and sometimes changing the format of the values) for # popular settings, as well as custom panel/desktop launchers. # # You need to run both the prepare and this test script as the same user, # in a full desktop session. # # (C) 2012 Canonical Ltd. # Author: Martin Pitt # License: GPL v2 or higher from __future__ import print_function import unittest import os, sys import subprocess from time import sleep try: from gi.repository import Gio except: # Not a desktop print("Failed to import gi.repository. Not a LTS Desktop Upgrade. Skipping!") sys.exit(0) class T(unittest.TestCase): def test_background(self): '''background image''' bg_settings = Gio.Settings('org.gnome.desktop.background') # note: original gconf value does not have a file:// prefix, but GNOME # 3.x requires this prefix self.assertEqual(bg_settings.get_string('picture-uri'), 'file://%s/mybackground.jpg' % os.environ['HOME']) # Theme is not preserved on upgrade. LP: #969569 # Test disabled # def test_gtk_theme(self): # '''GTK theme''' # # iface_settings = Gio.Settings('org.gnome.desktop.interface') # self.assertEqual(iface_settings.get_string('gtk-theme'), 'Radiance') def test_custom_launchers(self): '''Custom panel/desktop launchers appear in Unity launcher''' launcher_settings = Gio.Settings('com.canonical.Unity.Launcher') favorites = launcher_settings['favorites'] # gedit was dragged from Application menu to panel, pointing to system # .desktop file self.assertTrue('gedit.desktop' in favorites) # custom "echo hello" panel starter uses its own .desktop file for starter in favorites: if 'echo' in starter: self.assertTrue(os.path.exists(starter)) break else: self.fail('custom hello starter not found') # gucharmap was dragged from Application menu to desktop, should be # converted to system .desktop file self.assertTrue('gucharmap.desktop' in favorites) # custom "bc -l" desktop starter uses its own .desktop file self.assertTrue('%s/Desktop/termcalc.desktop' % os.environ['HOME'] in favorites) def test_keyboard_layouts(self): '''Custom keyboard layouts are migrated and applied''' # verify gconf->gsettings migration kbd_settings = Gio.Settings('org.gnome.libgnomekbd.keyboard') self.assertEqual(kbd_settings['layouts'], ['us','de\tnodeadkeys','gb','gb\tdvorak']) # NO DISPLAY IN AUTOMATED TEST # # verify that they get applied to the X server correctly # xprop = subprocess.Popen(['xprop', '-root', '_XKB_RULES_NAMES'], # stdout=subprocess.PIPE, universal_newlines=True) # out = xprop.communicate()[0] # self.assertEqual(xprop.returncode, 0) # # # chop off key name # out = out.split('=', 1)[1].strip() # # self.assertEqual(out, '"evdev", "pc105", "us,de,gb,gb", ",nodeadkeys,,dvorak", "grp:alts_toggle"') # Only run on lts-ubuntu testcases if not os.path.exists('/upgrade-tester/prepare_lts_desktop'): print("Not an Ubuntu Desktop LTS upgrade. Skipping!") sys.exit(0) if os.getuid() == 0: # Root ? reexecute itself as user ubuntu ret = subprocess.call('sudo -H -u ubuntu dbus-launch %s' % os.path.abspath(__file__), shell=True) sys.exit(ret) else: # Give 1 minute for the session to start, convert, ... sleep(60) unittest.main() auto-upgrade-testing/share/post_upgrade_tests/debconf_test.py0000775000000000000000000000401712076525005022056 0ustar #!/usr/bin/python """ Parse debconf log file and split in a file per prompt Exit with status 1 if there is a debconf prompt not in whitelist """ from __future__ import print_function import re, os, sys # Keep this path in sync with the corresponding setting in # profile/defaults.cfg.d/defaults.cfg DEBCONF_LOG_PATH = '/var/log/dist-upgrade/debconf.log' RESULT_DIR = '/tmp' # Prompts in this list won't generate a test failure # i.e WHITELIST = ['libraries/restart-without-asking'] WHITELIST = [ 'glibc/restart-services', 'libraries/restart-without-asking' ] def run_test(logfile, resultdir): """ Run the test and slice debconf log :param logfile: Path to debconf log :param resultdir: Output directory to write log file to """ global WHITELIST ret = 0 if not os.path.exists(logfile): return ret re_dsetting = re.compile('^\w') inprompt = False prompt = dsetting = "" with open(logfile, 'r') as f_in: for line in f_in.readlines(): # Only keep interesting bits of the prompt if line.startswith('#####'): inprompt = not inprompt # Reached the second separator, write content to result file # One per prompt if not inprompt: print("Got debconf prompt for '%s'" % dsetting) if dsetting in WHITELIST: print(' But it is in Whitelist. Skipping!') continue else: ret = 1 with open(os.path.join( resultdir, 'debconf_%s.log' % dsetting.replace('/', '_')), 'w') as f_out: f_out.write(prompt) if inprompt: prompt += line if re_dsetting.match(line) and '=' in line: dsetting = line.split('=')[0] return ret if __name__ == '__main__': sys.exit(run_test(DEBCONF_LOG_PATH, RESULT_DIR)) auto-upgrade-testing/share/post_upgrade_tests/test_conffiles.py0000775000000000000000000000502312076525005022424 0ustar #!/usr/bin/python # # This script checks status of configuration files after upgrade. # Current checks are: # - Obsolete config files # - Existence of *.dpkg-dist files. It means there was a prompt for an # unmodified configuration during upgrade # # (C) 2012 Canonical Ltd. # Author: Jean-Baptiste Lallement # License: GPL v2 or higher import unittest import subprocess import glob class TestConfFiles(unittest.TestCase): def test_obsolete_configfile(self): '''Check for obsolete config files after upgrade''' cmd = ['dpkg-query' ,'-W', '-f=${Package}\n${Conffiles}\n\n'] #output_file = '/var/log/dist-upgrade/obsolete_conffiles.log' output_file = '/tmp/obsolete_conffiles.log' test_output = '' dpkgquery = subprocess.check_output(cmd) current = set() obsolete = {} for pkg in dpkgquery.split('\n\n'): pkg = pkg.strip().split('\n') pkgname = pkg[0] cfgfiles = pkg[1:] for cfgfile in cfgfiles: cfgbits = cfgfile.strip().split() if len(cfgbits) < 3: # No status, not obsolete current.add(cfgbits[0]) else: file, md5, status = cfgbits[:3] if 'obsolete' in status: obsolete.setdefault(pkgname, []).append(file) else: current.add(file) for pkgname in sorted(obsolete.keys()): cfgfiles = [cfgfile for cfgfile in obsolete[pkgname] if cfgfile not in current] if cfgfiles: test_output += "%s\n %s\n" % (pkgname, "\n ".join(cfgfiles)) if test_output: with open(output_file, 'w') as f: print >>f, test_output def test_dpkgdist(self): '''Check for existence of *.dpkg-dist files''' whitelist_dpkg = [ '/tmp/sudoers.dpkg-dist', '/tmp/release-upgrades.dpkg-dist' ] cmd = ['find /etc -name "*.dpkg-dist" -exec cp \'{}\' /tmp \;'] subprocess.check_call(cmd, shell=True) dpkgdist_files = glob.glob('/tmp/*.dpkg-dist') dpkgdist_files = [ f for f in dpkgdist_files if f not in whitelist_dpkg] self.assertEqual( len(dpkgdist_files), 0, "*.dpkg-dist files found after upgrade:\n %s" % "\n ".join(dpkgdist_files)) if __name__ == '__main__': unittest.main() auto-upgrade-testing/share/post_upgrade_tests/test_python_import.py0000775000000000000000000001056112076525005023372 0ustar #!/usr/bin/python # # This script checks python. Current tests: # - import python modules available on the systen # # (C) 2012 Canonical Ltd. # Author: Jean-Baptiste Lallement # Based on original version from Michael Vogt # License: GPL v2 or higher import unittest import ConfigParser import os import logging import subprocess logging.basicConfig( filename='/tmp/%s.log' % os.path.basename(__file__)[:-3], filemode='w', level=logging.DEBUG) # stuff that we know does not work when doing a simple "import" BLACKLIST = ["speechd_config", "PAMmodule.so", "aomodule.so", "plannerui.so", "desktopcouch", # needs a KeyringDaemon "ropemacs", # just hangs "keyring", # needs X "invest", "Onboard", "goocanvasmodule.so", ] # If you want to test modules that require a display you'll have to install # xvfb in the base image XVFB_BIN='/usr/bin/xvfb-run' XVFB_OPT=[] def py_module_filter(pymodule): return not ( pymodule.endswith(".egg-info") or pymodule.endswith(".pth") or pymodule.startswith("_") or pymodule.endswith(".pyc") or pymodule.endswith("_d.so") or pymodule in BLACKLIST ) def get_module_from_path(path): f = os.path.basename(path) if path and os.path.exists(os.path.join(path, "__init__.py")): return f elif f.endswith(".py"): return f.split(".")[0] # swig uses this, calls it "foomodule.so" but the import is "foo" # (eg xdelta3module.so, pqueuemodule.so) elif f.endswith("module.so"): return f.split("modules.so")[0] elif f.endswith(".so"): return f.split(".")[0] class TestPython(unittest.TestCase): # total imports total = 0 failed = [] def _try_import(self, path): '''Try to import a module from a path a simple __import__(module) does not work, the problem is that module import have funny side-effects (like "import uno; import pyatspi" will fail, but importing them individually is fine ''' logging.info('Importing %s', path) module = get_module_from_path(path) rc = True if not module: logging.warn("could not get module for '%s'" % path) return rc try: cmd = ["python", "-c","import %s" % module] self.total += 1 subprocess.check_call(cmd, stderr = self.stderr) except subprocess.CalledProcessError: try: pkg = subprocess.check_output(["dpkg", "-S", os.path.realpath(path)]) self.failed.append((module, pkg.strip())) logging.error('Import failed. Package providing this module: %s', pkg) except subprocess.CalledProcessError: logging.error("Import of %s failed, and no package ships this module.", path) rc = False return rc def setUp(self): # Read default python version installed on the system config = ConfigParser.SafeConfigParser() config.read('/usr/share/python/debian_defaults') self.default_version = config.get('DEFAULT', 'default-version') self.distpackages = '/usr/lib/%s/dist-packages/' % self.default_version self.stderr = open('/tmp/%s.stderr' % os.path.basename(__file__)[:-3],'w') def tearDown(self): self.stderr.close() def test_python_import(self): '''Import python modules from /usr/lib/PYTHONVER/dist-packages/''' res = True for module in filter(py_module_filter, os.listdir(self.distpackages)): res &= self._try_import(os.path.join(self.distpackages, module)) logging.info('Modules imported: %d', self.total) if res: logging.info('No failure') self.assertTrue(res, '%d module(s) failed to import' % len(self.failed)) if __name__ == '__main__': if 'DISPLAY' in os.environ: unittest.main() elif os.path.exists(XVFB_BIN): logging.info("'%s' found and DISPLAY not set. Re-executing myself with xvfb") cmd = [ XVFB_BIN ] + XVFB_OPT + [os.path.abspath(__file__)] logging.info(cmd) subprocess.call(cmd) else: logging.warning("'%s' not found and DISPLAY not set. Executing test without a display", XVFB_BIN) unittest.main() auto-upgrade-testing/share/post_upgrade_tests/test_xserver.py0000775000000000000000000000265512076525005022162 0ustar #!/usr/bin/python # # This script checks that xserver is running # # (C) 2012 Canonical Ltd. # Author: Jean-Baptiste Lallement # Based on the original version from Michael Vogt # License: GPL v2 or higher import unittest import subprocess from time import sleep def is_process_running(procname): '''Check if a process is running''' proclist = subprocess.Popen(["ps","-eo","comm"], stdout=subprocess.PIPE, universal_newlines=True).communicate()[0] for line in proclist.split("\n"): if line == procname: return True return False def is_desktop_install(): '''Check that at least an *ubuntu-desktop package is installed''' cmd = ['dpkg-query', '-Wf', '${Status}\n', '*ubuntu-desktop'] try: output = subprocess.check_output(cmd).split('\n') except: return False for line in output: if line.startswith('install'): return True return False class TestXserver(unittest.TestCase): @unittest.skipIf(not is_desktop_install(), 'Not a desktop installation.') def test_xserver_running(self): '''Checking for running Xorg''' count = 0 while not is_process_running('Xorg') and count<10: count += 1 sleep(10) self.assertTrue(is_process_running('Xorg'), 'X Server not running') if __name__ == '__main__': unittest.main() auto-upgrade-testing/share/post_upgrade_tests/debsums_lite.py0000664000000000000000000000070412076525005022072 0ustar #!/usr/bin/python from __future__ import print_function import glob import os import subprocess import sys basepath = "/var/lib/dpkg/info/*.md5sums" ok = True for f in glob.glob(basepath): ret = subprocess.call(["md5sum", "--quiet", "-c", os.path.join(basepath, f)], cwd="/") if ret != 0: ok = False if not ok: print("WARNING: at least one md5sum mismatch") sys.exit(1) auto-upgrade-testing/share/post_upgrade_tests/README0000664000000000000000000000036612076525005017725 0ustar The scripts in this folder are run after the upgrade was performed and after a reboot. They can test various functionality like - is the latest kernel running - is the xserver running - is python still working - are my daemons still running etc auto-upgrade-testing/share/post_upgrade_tests/test_lts_upgrade_system.py0000775000000000000000000000452312076525005024375 0ustar #!/usr/bin/python # # This script checks system-wide configuration settings after an Ubuntu 10.04 # LTS to Ubuntu 12.04 LTS upgrade. Run this after upgrading to 12.04 or later. # It reads the old gdm settings and ensures that they were appropriately # migrated to lightdm and that lightdm is the default DM. # It does not need any particular privileges, it is fine to run this as any # user. # # (C) 2012 Canonical Ltd. # Author: Martin Pitt # License: GPL v2 or higher from __future__ import print_function import unittest import os, sys try: import configparser configparser # pyflakes except ImportError: import ConfigParser as configparser class T(unittest.TestCase): @classmethod def setUpClass(klass): # read gdm configuration klass.gdm_config = klass._read_conf('/etc/gdm/custom.conf', 'daemon') klass.lightdm_config = klass._read_conf('/etc/lightdm/lightdm.conf', 'SeatDefaults') def test_lightdm_default_dm(self): '''lightdm is the default display manager''' with open('/etc/X11/default-display-manager') as f: default_dm = f.read().strip() self.assertTrue(os.access(default_dm, os.X_OK)) self.assertEqual(os.path.basename(default_dm), 'lightdm') def test_autologin_migration(self): '''autologin migration from gdm to lightdm''' if self.gdm_config.get('automaticloginenable', 'false') == 'true': gdm_autologin = self.gdm_config.get('automaticlogin', '') else: gdm_autologin = '' self.assertEqual(gdm_autologin, self.lightdm_config.get('autologin-user', '')) @classmethod def _read_conf(klass, filename, section): '''Read section from an INI configuration file. Return a dictionary with the configuration of the given section. ''' p = configparser.ConfigParser() p.read(filename) config = {} try: for (key, value) in p.items(section): config[key] = value except configparser.NoSectionError: # just keep an empty config pass return config # Only run on lts-ubuntu testcases if not os.path.exists('/upgrade-tester/prepare_lts_desktop'): print("Not an Ubuntu Desktop LTS upgrade. Skipping!") sys.exit(0) if __name__ == '__main__': unittest.main() auto-upgrade-testing/share/post_upgrade_tests/test_kernel.py0000775000000000000000000000316412076525005021740 0ustar #!/usr/bin/python # # This script checks for that at least 2 kernels are installed post-upgrade # and that the latest one is active # # (C) 2012 Canonical Ltd. # Author: Jean-Baptiste Lallement # Based on the original version from Michael Vogt # License: GPL v2 or higher import unittest import apt_pkg import glob import os class TestKernel(unittest.TestCase): def setUp(self): apt_pkg.init() self.current_kernelversion = os.uname()[2] self.versions = set() for kernel in glob.glob('/boot/vmlinuz-*'): version = "-".join(kernel.split("-")[1:4]) self.versions.add(version) def test_kernel_in_use(self): '''Check latest kernel is in use''' if os.path.exists("/run/container_type"): with open("/run/container_type") as fd: container = fd.read().strip() print("Skipping test_kernel_in_use as in a '%s' container." % container) return for version in self.versions: self.assertFalse( apt_pkg.version_compare(self.current_kernelversion, version) < 0, "There is a kernel version '%s' installed higher than the running kernel '%s'" % (version, self.current_kernelversion)) def test_old_kernel_is_installed(self): '''Check that previous kernel is still there after install''' self.assertNotEqual( len(self.versions), 1, "Only one kernel found '%s', expected at least 2 (new + previous)" % self.versions) if __name__ == '__main__': unittest.main() auto-upgrade-testing/share/install_blacklist.cfg0000664000000000000000000000144412076525005017304 0ustar # file-overwrite problem with libc6-dev libpthread-dev # FUBAR (was removed in feisty) glibc-doc-reference # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # the following packages try to access /lib/modules/`uname -r` and fail vmware-player-kernel-.* # not installable on a regular machine ltsp-client ltsp-client-core # why is this in the archive? debsig-verify # speedbar,ede fails for some reason speedbar ede ecb emacs-snapshot # ec2 ec2-init linux-image-ec2 linux-image-2.6.31-302-ec2 bacula-director-mysql linux-backports-modules-wireless-2.6.32-21-generic-pae linux-backports-modules-wireless-2.6.32-22-generic-pae linux-backports-modules-wireless-2.6.32-23-generic-pae linux-backports-modules-wireless-2.6.32-24-generic-pae # no fun cloud-init eucalyptus-.*auto-upgrade-testing/share/scripts/0000775000000000000000000000000012076525005014611 5ustar auto-upgrade-testing/share/scripts/randomInst0000775000000000000000000000115412076525005016656 0ustar #!/usr/bin/python3 from __future__ import print_function import sys import apt from random import choice cache = apt.Cache() for i in range(int(sys.argv[1])): while True: pkgname = choice(cache.keys()) if cache[pkgname].is_installed: continue try: print("Trying to install: '%s'" % pkgname) cache[pkgname].mark_install() except SystemError as e: print("Failed to install '%s' (%s)" % (pkgname, e)) continue break cache.commit(apt.progress.text.AcquireProgress(), apt.progess.base.InstallProgress()) auto-upgrade-testing/share/scripts/README.jeos-create-base-image0000664000000000000000000000316112076525005021662 0ustar Create the images by simply running $ ./create-base-image.sh maverick (or whatever distroibution release you want to create) ===== old info below ==== Images created with: First create a ssh key: $ ssh-keygen -N '' -f ssh-key [intrepid] Can use the official ubuntu-vm-builder pacakges] $ sudo ubuntu-vm-builder kvm intrepid --kernel-flavour generic --ssh-key `pwd`/ssh-key.pub --components main,restricted --rootsize 80000 --arch i386 $ mv ubuntu-kvm/disk0.qcow2 intrepid-i386.qcow2 - login and check if openssh-server is installed (intrepid ubuntu-vm-builder FTW) For old releases: $ bzr get http://bazaar.launchpad.net/~mvo/ubuntu-jeos/mvo [hardy] $ ./ubuntu-jeos-builder --vm kvm --kernel-flavour generic --suite hardy --ssh-key `pwd`/ssh-key.pub --components main,restricted --rootsize 80G --no-opt [gutsy] $ ./ubuntu-jeos-builder --vm kvm --kernel-flavour generic --suite gutsy --ssh-key `pwd`/ssh-key.pub --components main,restricted --rootsize 80G --no-opt [feisty] $ ./ubuntu-jeos-builder --vm kvm --kernel-flavour generic --suite feisty --ssh-key `pwd`/ssh-key.pub --components main,restricted --rootsize 80G --no-opt [dapper] $ ./ubuntu-jeos-builder --vm kvm --kernel-flavour 386 --suite dapper --ssh-key `pwd`/foo.pub --components main,restricted --rootsize 80G --no-opt (notice the different kernel names for dapper,feisty). The ssh-key is the key that is used by the upgrade tester to log into the virtual machine. The copy it from "jeos/ubuntu-jeos-$dist-i386/root.qcow2" to "jeos/$dist-i386.qcow2" Make sure you copy the "ssh-key" file into the profile dir so that the upgrade tester can access it auto-upgrade-testing/share/scripts/chart_dpkg_progress0000775000000000000000000000244012076525005020571 0ustar #!/usr/bin/python3 from __future__ import print_function import sys from heapq import heappush, heappop if __name__ == "__main__": start_time = 0.0 last_time = 0.0 total_time = 0.0 pkgs = {} last_pkgname = None log = open(sys.argv[1]) for line in log: line = line.strip() line_data = line.split(":") # special cases if line_data[1].strip() == "Start": start_time = float(line_data[0]) continue elif line_data[1].strip() == "Finished": total_time = float(line_data[0]) - start_time continue # we have a real pkg here current_time = float(line_data[0]) pkgname = line_data[2] # special cases if not last_time: last_time = current_time if not pkgname in pkgs: pkgs[pkgname] = 0 # add up time if last_pkgname: pkgs[last_pkgname] += (current_time-last_time) last_time = current_time last_pkgname = pkgname # put into heap and output by time it takes heap = [] for pkg in pkgs: heappush(heap, (pkgs[pkg], pkg)) while heap: print("%.6ss: %s" % heappop(heap)) print("total: %4.7ss %4.6sm" % (total_time, total_time/60)) auto-upgrade-testing/share/scripts/prepare_lts_user0000775000000000000000000001151412076525005020117 0ustar #!/bin/sh # This script sets some popular user configuration settings in an Ubuntu 10.04 # LTS GNOME system. Run this, then upgrade to 12.04 LTS (or later), and run # test_lts_upgrade_user.py to confirm that settings were migrated properly. In # particular this checks for gconf -> gsettings migration (and sometimes # changing the format of the values) for popular settings, as well as custom # panel/desktop launchers. # # You need to run this script in a fully running GNOME desktop session. # # (C) 2012 Canonical Ltd. # Author: Martin Pitt # License: GPL v2 or higher set -e echo "Setting custom background..." cp `ls /usr/share/backgrounds/*.jpg | head -n1` $HOME/mybackground.jpg gconftool -s /desktop/gnome/background/picture_filename --type string $HOME/mybackground.jpg echo "Setting Radiance theme..." gconftool -s /desktop/gnome/interface/gtk_theme --type string Radiance echo "Adding custom panel launchers..." # add launcher for system desktop file (gedit) gconftool -s /apps/panel/objects/object_0/menu_path --type string 'applications:/' gconftool -s /apps/panel/objects/object_0/launcher_location --type string '/usr/share/applications/gedit.desktop' gconftool -s /apps/panel/objects/object_0/bonobo_iid --type string '' gconftool -s /apps/panel/objects/object_0/custom_icon --type string '' gconftool -s /apps/panel/objects/object_0/locked --type bool false gconftool -s /apps/panel/objects/object_0/panel_right_stick --type bool false gconftool -s /apps/panel/objects/object_0/object_type --type string 'launcher-object' gconftool -s /apps/panel/objects/object_0/use_custom_icon --type bool false gconftool -s /apps/panel/objects/object_0/tooltip --type string '' gconftool -s /apps/panel/objects/object_0/toplevel_id --type string 'top_panel_screen0' gconftool -s /apps/panel/objects/object_0/action_type --type string 'lock' gconftool -s /apps/panel/objects/object_0/use_menu_path --type bool false gconftool -s /apps/panel/objects/object_0/position --type int 60 gconftool -s /apps/panel/objects/object_0/attached_toplevel_id --type string '' # add launcher for custom desktop file mkdir -p $HOME/.gnome2/panel2.d/default/launchers/ mkdir -p $HOME/Desktop cat < $HOME/.gnome2/panel2.d/default/launchers/echo-1.desktop #!/usr/bin/env xdg-open [Desktop Entry] Version=1.0 Type=Application Terminal=true Icon[en_US]=partner Name[en_US]=hello Exec=echo hello Name=hello Icon=gnome-panel-launcher EOF chmod 755 $HOME/.gnome2/panel2.d/default/launchers/echo-1.desktop gconftool -s /apps/panel/objects/object_1/menu_path --type string 'applications:/' gconftool -s /apps/panel/objects/object_1/launcher_location --type string 'echo-1.desktop' gconftool -s /apps/panel/objects/object_1/bonobo_iid --type string '' gconftool -s /apps/panel/objects/object_1/custom_icon --type string '' gconftool -s /apps/panel/objects/object_1/locked --type bool false gconftool -s /apps/panel/objects/object_1/panel_right_stick --type bool false gconftool -s /apps/panel/objects/object_1/object_type --type string 'launcher-object' gconftool -s /apps/panel/objects/object_1/use_custom_icon --type bool false gconftool -s /apps/panel/objects/object_1/tooltip --type string '' gconftool -s /apps/panel/objects/object_1/toplevel_id --type string 'top_panel_screen0' gconftool -s /apps/panel/objects/object_1/action_type --type string 'lock' gconftool -s /apps/panel/objects/object_1/use_menu_path --type bool false gconftool -s /apps/panel/objects/object_1/position --type int 90 gconftool -s /apps/panel/objects/object_1/attached_toplevel_id --type string '' # add the two new launchers to the panel object list old_list=`gconftool -g /apps/panel/general/object_id_list | sed 's/]$//'` gconftool -s /apps/panel/general/object_id_list --type list --list-type string "$old_list,object_0,object_1]" echo "Adding custom desktop launchers ..." cat < $HOME/Desktop/gucharmap.desktop #!/usr/bin/env xdg-open [Desktop Entry] Name=Character Map Comment=Insert special characters into documents Exec=gucharmap Icon=accessories-character-map Terminal=false Type=Application Categories=GNOME;GTK;Utility; X-GNOME-Bugzilla-Bugzilla=GNOME X-GNOME-Bugzilla-Product=gucharmap X-GNOME-Bugzilla-Component=general X-GNOME-Bugzilla-Version=2.30.0 StartupNotify=true X-Ubuntu-Gettext-Domain=gucharmap EOF chmod 755 $HOME/Desktop/gucharmap.desktop cat < $HOME/Desktop/termcalc.desktop #!/usr/bin/env xdg-open [Desktop Entry] Version=1.0 Type=Application Terminal=true Icon[en_US]=/usr/share/icons/gnome/scalable/apps/calc.svg Name[en_US]=termcalc Exec=bc -l Name=termcalc Icon=/usr/share/icons/gnome/scalable/apps/calc.svg EOF chmod 755 $HOME/Desktop/termcalc.desktop echo "Setting custom keyboard layouts..." gconftool -s /desktop/gnome/peripherals/keyboard/kbd/layouts --type list --list-type string "[us,de nodeadkeys,gb,gb dvorak]" echo 'Success. Now upgrade to 12.04 LTS and run test_lts_upgrade_user.py' auto-upgrade-testing/share/scripts/apt-watchdog0000775000000000000000000000257712076525005017134 0ustar #!/usr/bin/python3 # # this is watchdog that will try to kill hanging apt-get installs # that may happen when the auto-install-tester runs # # its probably not useful for anything else from __future__ import print_function import os import signal import subprocess import sys import time # default kill time 60min WAKEUP_INTERVAL = 60*60 def watchdog_loop(): watch_files = ["/var/log/apt/term.log", "/var/log/dist-upgrade/apt-term.log"] mtime = 0 while True: for f in watch_files: if os.path.exists(f): mtime = max(mtime, os.path.getmtime(f)) time.sleep(WAKEUP_INTERVAL) for f in watch_files: if os.path.exists(f): if os.path.getmtime(f) > mtime: break else: print("no mtime change for %s seconds, sending SIGINT" % WAKEUP_INTERVAL) subprocess.call(["killall","-INT","apt-get"]) if __name__ == "__main__": print("Starting apt watchdog daemon for the auto-install-tester") if len(sys.argv) > 1 and sys.argv[1] == "--no-daemon": watchdog_loop() # do the daemon thing pid = os.fork() if pid == 0: os.setsid() signal.signal(signal.SIGHUP, signal.SIG_IGN) watchdog_loop() else: # add a little sleep to ensure child is setup time.sleep(10) os._exit(0) auto-upgrade-testing/share/scripts/jeos-create-base-image0000775000000000000000000000126512076525005020734 0ustar #!/bin/sh set -e DIST=$(lsb_release -c -s) if [ -z "$1" ]; then echo "need distro codename to create as first argument " exit 1 fi # check depends if [ ! -f /usr/bin/ubuntu-vm-builder ]; then apt-get install -y ubuntu-vm-builder fi if [ ! -f /usr/bin/kvm ]; then apt-get install -y kvm fi # create a default ssh key if [ ! -e ssh-key ]; then ssh-keygen -N '' -f ssh-key fi KERNEL=generic if [ "$1" = "dapper" ]; then KERNEL=386 fi # create the image ubuntu-vm-builder kvm $1 --kernel-flavour $KERNEL --ssh-key $(pwd)/ssh-key.pub \ --components main,restricted --rootsize 80000 --arch i386 --dest ubuntu-$1 # move into place mv ubuntu-$1/*.qcow2 $1-i386.qcow2 auto-upgrade-testing/share/scripts/run_and_publish_tests0000775000000000000000000000366112076525005021143 0ustar #!/bin/sh # -------------------------------------------------------------- config # link to the ssh key to publish the results SSHKEY="-oIdentityFile=link-to-ssh-key" PUBLISH="mvo@people.ubuntu.com" #PUBLISH="" RESULTDIR=/var/cache/auto-upgrade-tester/result/ # output DATE=$(date +"%F-%T") HTML_BASEDIR=~/public_html/automatic-upgrade-testing HTMLDIR=$HTML_BASEDIR/$DATE PROFILES="server server-tasks ubuntu kubuntu main-all" #PROFILES="lts-server server" #PROFILES="server" UPGRADE_TESTER_ARGS="--quiet --html-output-dir $HTMLDIR" #UPGRADE_TESTER_ARGS="$UPGRADE_TESTER_ARGS -b UpgradeTestBackendSimulate " #UPGRADE_TESTER_ARGS="$UPGRADE_TESTER_ARGS --tests-only" upload_files() { profile=$1 SSHKEY=$2 PUBLISH=$3 DATE=$4 cat > sftp-upload </dev/null } upload_index_html() { SSHKEY=$1 PUBLISH=$2 DATE=$3 # upload index cat > sftp-upload </dev/null } update_current_symlink() { SSHKEY=$1 PUBLISH=$2 cat > sftp-upload </dev/null } # ------------------------------------------------------------- main() bzr up FAIL="" PROFILES_ARG="" for p in $PROFILES; do # clear log dir first rm -f $RESULTDIR/$p/* # do it PROFILES_ARG=" $PROFILES_ARG profile/$p" done # run with the profiles we have ./auto-upgrade-tester $UPGRADE_TESTER_ARGS $PROFILES_ARG # update current symlink rm -f $HTML_BASEDIR/current ln -s $DATE $HTML_BASEDIR/current # FIXME: portme #upload_index_html $SSHKEY $PUBLISH $DATE #update_current_symlink $SSHKEY $PUBLISH auto-upgrade-testing/share/scripts/install_all_main0000775000000000000000000000546112076525005020047 0ustar #!/usr/bin/python3 from __future__ import print_function import apt import apt_pkg def blacklisted(name): # we need to blacklist linux-image-* as it does not install # cleanly in the chroot (postinst failes) blacklist = ["linux-image-","ltsp-client", "glibc-doc-reference", "libpthread-dev", "cman", "mysql-server", "fuse-utils", "ltspfs", "gfs2-tools", "edubuntu-server", "gnbd-client", "gnbd-server", "mysql-server-5.0", "rgmanager", "clvm","redhat-cluster-suit", # has a funny "can not be upgraded automatically" policy # see debian #368226 "quagga", "system-config-cluster", "gfs-tools"] for b in blacklist: if name.startswith(b): return True return False #apt_pkg.config.set("Dir::State::status","./empty") cache = apt.Cache() group = apt_pkg.ActionGroup(cache._depcache) #print([pkg.name for pkg in cache if pkg.is_installed]) troublemaker = set() for pkg in cache: if not pkg.candidate: continue for c in pkg.candidate.origins: if c.component == "main": current = set([p.name for p in cache if p.marked_install]) if not (pkg.is_installed or blacklisted(pkg.name)): pkg.mark_install() new = set([p.name for p in cache if p.marked_install]) #if not pkg.marked_install or len(new) < len(current): if not (pkg.is_installed or pkg.marked_install): print("Can't install: %s" % pkg.name) if len(current-new) > 0: troublemaker.add(pkg.name) print("Installing '%s' caused removals_ %s" % (pkg.name, current - new)) #print(len(troublemaker)) for pkg in ["ubuntu-desktop", "ubuntu-minimal", "ubuntu-standard"]: cache[pkg].mark_install() # make sure we don't install blacklisted stuff for pkg in cache: if blacklisted(pkg.name): pkg.mark_keep() print("We can install:") print(len([pkg.name for pkg in cache if pkg.marked_install])) print("Download: ") pm = apt_pkg.PackageManager(cache._depcache) fetcher = apt_pkg.Acquire() pm.get_archives(fetcher, cache._list, cache._records) print(apt_pkg.size_to_str(fetcher.fetch_needed)) print("Total space: ", apt_pkg.size_to_str(cache._depcache.usr_size)) res = False current = 0 maxRetries = 3 while current < maxRetries: try: res = cache.commit(apt.progress.text.AcquireProgress(), apt.progress.base.InstallProgress()) except IOError as e: # fetch failed, will be retried current += 1 print("Retrying to fetch: ", current) continue except SystemError as e: print("Error installing packages! ") print(e) print("Install result: ", res) break auto-upgrade-testing/share/scripts/install_all0000775000000000000000000001766012076525005017047 0ustar #!/usr/bin/python3 from __future__ import print_function import apt import apt_pkg import re import os import sys # global install blacklist pkg_blacklist = None # whitelist regexp to include only certain packages (useful for e.g. # installing only all python packages) pkg_whitelist = "" class InstallProgress(apt.progress.base.InstallProgress): " Out install progress that can automatically remove broken pkgs " def error(self, pkg, errormsg): # on failure: # - add failing package to "install_failures.txt" [done] # - remove package from best.txt [done] # FIXME: - remove all rdepends from best.txt # - remove the failed install attempts [done] # * explode if a package can not be removed and let the user cleanup open("install_failures.txt","a").write("%s _:_ %s" % (pkg, errormsg)) bad = set() bad.add(os.path.basename(pkg).split("_")[0]) # FIXME: just run apt-cache rdepends $pkg here? # or use apt.Package.candidate.dependencies ? # or calculate the set again? <- BEST! for name in bad: new_best = open("best.txt").read().replace(name+"\n","") open("best.txt","w").write(new_best) open("install_blacklist.cfg","a").write("# auto added by install_all.py\n%s\n" % name) def do_install(cache): # go and install res = False current = 0 maxRetries = 5 while current < maxRetries: print("Retry: ", current) try: res = cache.commit(apt.progress.text.AcquireProgress(), InstallProgress()) break except IOError as e: # fetch failed, will be retried current += 1 print("Retrying to fetch: ", current, e) continue except SystemError as e: print("Error installing packages! ") print(e) print("Install result: ", res) break # check for failed packages and remove them if os.path.exists("install_failures.txt"): with open("install_failures.txt") as install_failures: failures = set([os.path.basename(s.split("_:_")[0]).split("_")[0] for s in install_failures]) print("failed: ", failures) assert(os.system("dpkg -r %s" % " ".join(failures)) == 0) assert(os.system("dpkg --configure -a") == 0) # remove pos.txt and best.txt to force recalculation os.unlink("pos.txt") os.unlink("best.txt") return res def blacklisted(name): global pkg_blacklist if pkg_blacklist is None and os.path.exists("install_blacklist.cfg"): pkg_blacklist = set() with open("install_blacklist.cfg") as blacklist_file: for line in blacklist_file: name = line.strip() if name and not name.startswith("#"): pkg_blacklist.add(name) print("blacklist: ", pkg_blacklist) if pkg_blacklist: for b in pkg_blacklist: if re.match(b, name): return True return False def reapply(cache, pkgnames): for name in pkgnames: cache[name].mark_install(False) def contains_blacklisted_pkg(cache): for pkg in cache: if pkg.marked_install and blacklisted(pkg.name): return True return False # ---------------------------------------------------------------- #apt_pkg.config.set("Dir::State::status","./empty") # debug stuff #apt_pkg.config.set("Debug::pkgProblemResolver","true") #apt_pkg.config.set("Debug::pkgDepCache::AutoInstall","true") #apt_pkg.config.set("Debug::pkgDpkgPM","true") # Increase the maxsize limits here # # this code in apt that splits the argument list if its too long # is problematic, because it may happen that # the argument list is split in a way that A depends on B # and they are in the same "--configure A B" run # - with the split they may now be configured in different # runs apt_pkg.config.set("Dpkg::MaxArgs",str(16*1024)) apt_pkg.config.set("Dpkg::MaxArgBytes",str(64*1024)) print("install_all.py") os.environ["DEBIAN_FRONTEND"] = "noninteractive" os.environ["APT_LISTCHANGES_FRONTEND"] = "none" cache = apt.Cache() # dapper does not have this yet group = cache.actiongroup() #print([pkg.name for pkg in cache if pkg.is_installed]) # see what gives us problems troublemaker = set() best = set() # first install all of main, then the rest comps= ["main","universe"] i=0 # reapply checkpoints if os.path.exists("best.txt"): with open("best.txt") as best_file: best = [line.strip() for line in best_file] reapply(cache, best) if os.path.exists("pos.txt"): (comp, i) = open("pos.txt").read().split() i = int(i) if comp == "universe": comps = ["universe"] sorted_pkgs = cache.keys()[:] sorted_pkgs.sort() for comp in comps: for pkgname in sorted_pkgs[i:]: # skip multiarch packages if ":" in pkgname: continue pkg = cache[pkgname] i += 1 percent = (float(i)/len(cache))*100.0 print("\r%.3f " % percent, end="") sys.stdout.flush() # ignore stuff that does not match the whitelist pattern # (if we use this) if pkg_whitelist: if not re.match(pkg_whitelist, pkg.name): #print("skipping '%s' (not in whitelist)" % pkg.name) continue print("looking at ", pkg.name) # only work on stuff that has a origin if pkg.candidate: for c in pkg.candidate.origins: if comp == None or c.component == comp: current = set([p.name for p in cache if p.marked_install]) if not (pkg.is_installed or blacklisted(pkg.name)): try: pkg.mark_install() except SystemError as e: print("Installing '%s' cause problems: %s" % (pkg.name, e)) pkg.mark_keep() # check blacklist if contains_blacklisted_pkg(cache): cache.clear() reapply(cache, best) continue new = set([p.name for p in cache if p.marked_install]) #if not pkg.marked_install or len(new) < len(current): if not (pkg.is_installed or pkg.marked_install): print("Can't install: %s" % pkg.name) if len(current-new) > 0: troublemaker.add(pkg.name) print("Installing '%s' caused removals %s" % (pkg.name, current - new)) # FIXME: instead of len() use score() and score packages # according to criteria like "in main", "priority" etc if len(new) >= len(best): best = new open("best.txt","w").write("\n".join(best)) open("pos.txt","w").write("%s %s" % (comp, i)) else: print("Installing '%s' reduced the set (%s < %s)" % (pkg.name, len(new), len(best))) cache.clear() reapply(cache, best) i=0 # make sure that the ubuntu base packages are installed (and a bootloader) print(len(troublemaker)) for pkg in ["ubuntu-desktop", "ubuntu-minimal", "ubuntu-standard", "grub-pc"]: cache[pkg].mark_install() # make sure we don't install blacklisted stuff for pkg in cache: if blacklisted(pkg.name): pkg.mark_keep() # install it print("We can install:", len([pkg.name for pkg in cache if pkg.marked_install])) # get size pm = apt_pkg.PackageManager(cache._depcache) fetcher = apt_pkg.Acquire() pm.get_archives(fetcher, cache._list, cache._records) print("Download: ", apt_pkg.size_to_str(fetcher.fetch_needed)) print("Total space: ", apt_pkg.size_to_str(cache._depcache.usr_size)) # write out file with all pkgs outf = "all_pkgs.cfg" print("writing out file with the selected package names to '%s'" % outf) f = open(outf, "w") f.write("\n".join([pkg.name for pkg in cache if pkg.marked_install])) f.close() # now do the real install res = do_install(cache) if not res: # FIXME: re-exec itself sys.exit(1) sys.exit(0) auto-upgrade-testing/share/scripts/prepare_lts_desktop0000775000000000000000000000062212076525005020610 0ustar #!/bin/sh # Setup Autologin cat > /etc/gdm/custom.conf < 0: troublemaker.add(pkg.name) print("Installing '%s' caused removals %s" % (pkg.name, current - new)) # FIXME: instead of len() use score() and score packages # according to criteria like "in main", "priority" etc if len(new) >= len(best): best = new open("best.txt","w").write("\n".join(best)) open("pos.txt","w").write("%s %s" % (comp, i)) else: print("Installing '%s' reduced the set (%s < %s)" % (pkg.name, len(new), len(best))) cache.clear() reapply(cache, best) i=0 # make sure that the ubuntu base packages are installed (and a bootloader) print(len(troublemaker)) for pkg in ["ubuntu-desktop", "ubuntu-minimal", "ubuntu-standard", "grub-pc"]: cache[pkg].mark_install() # make sure we don't install blacklisted stuff for pkg in cache: if blacklisted(pkg.name): pkg.mark_keep() # install it print("We can install:", len([pkg.name for pkg in cache if pkg.marked_install])) # get size pm = apt_pkg.PackageManager(cache._depcache) fetcher = apt_pkg.Acquire() pm.get_archives(fetcher, cache._list, cache._records) print("Download: ", apt_pkg.size_to_str(fetcher.fetch_needed)) print("Total space: ", apt_pkg.size_to_str(cache._depcache.usr_size)) # write out file with all pkgs outf = "all_pkgs.cfg" print("writing out file with the selected package names to '%s'" % outf) f = open(outf, "w") f.write("\n".join([pkg.name for pkg in cache if pkg.marked_install])) f.close() # now do the real install res = do_install(cache) if not res: # FIXME: re-exec itself sys.exit(1) sys.exit(0) auto-upgrade-testing/share/profiles/0000775000000000000000000000000012076525005014745 5ustar auto-upgrade-testing/share/profiles/lts-universe-i386/0000775000000000000000000000000012076525005020074 5ustar auto-upgrade-testing/share/profiles/lts-universe-i386/result/0000775000000000000000000000000012076525005021412 5ustar auto-upgrade-testing/share/profiles/lts-universe-i386/install_blacklist.cfg0000664000000000000000000000121512076525005024252 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity # Breaks apache lwat # Broken on collectd kcollectd # Failed to install on lucid global likewise-open likewise-open-gui auto-upgrade-testing/share/profiles/lts-universe-i386/DistUpgrade.cfg0000664000000000000000000000040212076525005022764 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName = lts-universe-i386 AdditionalPkgs = pkgs.cfg Components=main,restricted,universe PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_universe [KVM] VirtualRam = 3072 auto-upgrade-testing/share/profiles/lts-universe-i386/pkgs.cfg0000664000000000000000000000004412076525005021517 0ustar grub-pc python-apt app-install-data auto-upgrade-testing/share/profiles/kubuntu/0000775000000000000000000000000012076525005016442 5ustar auto-upgrade-testing/share/profiles/kubuntu/result/0000775000000000000000000000000012076525005017760 5ustar auto-upgrade-testing/share/profiles/kubuntu/DistUpgrade.cfg0000664000000000000000000000007712076525005021342 0ustar [NonInteractive] ProfileName=kubuntu BasePkg = kubuntu-desktop auto-upgrade-testing/share/profiles/lts-main-all-amd64/0000775000000000000000000000000012076525005020150 5ustar auto-upgrade-testing/share/profiles/lts-main-all-amd64/removal_blacklist.cfg0000664000000000000000000000035412076525005024330 0ustar # blacklist of packages that should never be removed ubuntu-standard ubuntu-minimal ubuntu-desktop kubuntu-desktop edubuntu-desktop gobuntu-desktop # never remove nvidia-glx and friends ^nvidia-glx$ ^nvidia-glx-new$ ^nvidia-glx-legacy$ auto-upgrade-testing/share/profiles/lts-main-all-amd64/install_blacklist.cfg0000664000000000000000000000144112076525005024327 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity # No need for so many kernels linux-image-.* # Failed to install bacula-director-mysql dovecot-common rabbitmq-server # cloud/ec2 no fun cloud-init ec2-init linux-image-ec2 linux-image-2.6.31-302-ec2 # not installable on a regular machine ltsp-client ltsp-client-core auto-upgrade-testing/share/profiles/lts-main-all-amd64/DistUpgrade.cfg0000664000000000000000000000046012076525005023044 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName = lts-main-all-amd64 AdditionalPkgs = pkgs.cfg PostBootstrapScript=/usr/share/pyshared/AutoUpgradeTester/install_all.py ;PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_all.py [KVM] Arch=amd64 VirtualRam=3072 auto-upgrade-testing/share/profiles/lts-main-all-amd64/DistUpgrade.cfg.dapper0000664000000000000000000000312312076525005024315 0ustar [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive # Distro contains global information about the upgrade [Distro] # the meta-pkgs we support MetaPkgs=ubuntu-desktop, kubuntu-desktop, edubuntu-desktop, xubuntu-desktop BaseMetaPkgs=ubuntu-minimal, ubuntu-standard PostUpgradePurge=xorg-common, libgl1-mesa Demotions=demoted.cfg RemoveEssentialOk=sysvinit RemovalBlacklistFile=removal_blacklist.cfg # information about the individual meta-pkgs [ubuntu-desktop] KeyDependencies=gdm, gnome-panel, ubuntu-artwork # those pkgs will be marked remove right after the distUpgrade in the cache PostUpgradeRemove=xchat, xscreensaver [kubuntu-desktop] KeyDependencies=kdm, kicker, kubuntu-artwork-usplash # those packages are marked as obsolete right after the upgrade ForcedObsoletes=ivman [edubuntu-desktop] KeyDependencies=edubuntu-artwork, tuxpaint [xubuntu-desktop] KeyDependencies=xubuntu-artwork-usplash, xubuntu-default-settings, xfce4 [Files] BackupExt=distUpgrade [Sources] From=dapper To=hardy ValidOrigin=Ubuntu ValidMirrors = mirrors.cfg [Network] MaxRetries=3 [PreRequists] Packages=release-upgrader-apt,release-upgrader-dpkg SourcesList=prerequists-sources.list [NonInteractive] ProfileName = main-all BasePkg = ubuntu-standard AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu Proxy=http://192.168.1.1:3128/ ForceOverwrite=yes CacheTarball=yes PostBootstrapScript=install_all.py Components=main,restricted Pockets=security,updates BaseImage=jeos/dapper-i386.qcow2 CacheBaseImage=yes SwapImage=jeos/swap.qcow2 UpgradeFromDistOnBootstrap=true SSHKey=ssh-key ReadReboot=yesauto-upgrade-testing/share/profiles/lts-main-all-amd64/pkgs.cfg0000664000000000000000000000005112076525005021571 0ustar python-apt python-gnupginterface grub-pc auto-upgrade-testing/share/profiles/lts-main-all-amd64/demoted.cfg0000664000000000000000000000000012076525005022240 0ustar auto-upgrade-testing/share/profiles/lts-main-all-amd64/prerequists-sources.list0000664000000000000000000000053512076525005025117 0ustar # sources.list fragment for pre-requists (one with countrymirror, one fallback) deb http://archive.ubuntu.com/ubuntu dapper-backports main/debian-installer #deb http://archive.ubuntu.com/ubuntu feisty-backports main/debian-installer # below is just for testing #deb http://archive.dogfood.launchpad.net/ubuntu feisty-backports main/debian-installer auto-upgrade-testing/share/profiles/quantal-server-tasks-amd64/0000775000000000000000000000000012076525005021752 5ustar auto-upgrade-testing/share/profiles/quantal-server-tasks-amd64/DistUpgrade.cfg0000664000000000000000000000023312076525005024644 0ustar [DEFAULT] SourceRelease=precise TargetRelease=quantal [NonInteractive] ProfileName=quantal-server-tasks-amd64 AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/quantal-server-tasks-amd64/pkgs.cfg0000664000000000000000000000020512076525005023374 0ustar python-apt python-gnupginterface dns-server^ lamp-server^ mail-server^ openssh-server^ postgresql-server^ print-server^ samba-server^auto-upgrade-testing/share/profiles/lts-server-amd64/0000775000000000000000000000000012076525005017764 5ustar auto-upgrade-testing/share/profiles/lts-server-amd64/DistUpgrade.cfg0000664000000000000000000000017112076525005022657 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName=lts-server-amd64 AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/lts-server-amd64/pkgs.cfg0000664000000000000000000000005112076525005021405 0ustar grub-pc python-apt python-gnupginterface auto-upgrade-testing/share/profiles/mythbuntu/0000775000000000000000000000000012076525005017004 5ustar auto-upgrade-testing/share/profiles/mythbuntu/DistUpgrade.cfg0000664000000000000000000000016412076525005021701 0ustar [NonInteractive] ProfileName = mythbuntu BasePkg = mythbuntu-desktop Components=main,restricted,universe,multiverse auto-upgrade-testing/share/profiles/universe-amd64/0000775000000000000000000000000012076525005017516 5ustar auto-upgrade-testing/share/profiles/universe-amd64/result/0000775000000000000000000000000012076525005021034 5ustar auto-upgrade-testing/share/profiles/universe-amd64/install_blacklist.cfg0000664000000000000000000000110712076525005023674 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity # Breaks apache lwat # Broken on collectd kcollectd auto-upgrade-testing/share/profiles/universe-amd64/DistUpgrade.cfg0000664000000000000000000000035512076525005022415 0ustar [NonInteractive] ProfileName = universe-amd64 AdditionalPkgs = pkgs.cfg Components=main,restricted,universe PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_universe [KVM] arch = amd64 VirtualRam = 3072 auto-upgrade-testing/share/profiles/universe-amd64/pkgs.cfg0000664000000000000000000000004412076525005021141 0ustar grub-pc python-apt app-install-data auto-upgrade-testing/share/profiles/auto-install-tester/0000775000000000000000000000000012076525005020665 5ustar auto-upgrade-testing/share/profiles/auto-install-tester/DistUpgrade.cfg0000664000000000000000000000257712076525005023574 0ustar [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive [Distro] BaseMetaPkgs=ubuntu-minimal, ubuntu-standard [Aufs] ;EnableFullOverlay=yes ;EnableChrootOverlay=yes ;EnableChrootRsync=yes [Sources] From=lucid To=lucid [NonInteractive] ProfileName=auto-install-tester BasePkg = ubuntu-standard AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu ;Mirror = http://us.ec2.archive.ubuntu.com/ubuntu ;Proxy=http://192.168.1.1:3128/ ForceOverwrite=no Components=main,restricted,universe Pockets=security,updates UpgradeFromDistOnBootstrap=true ;AddRepo=local_testing.list DpkgProgressLog=yes ResultDir=/var/cache/auto-upgrade-tester/result SSHKey=/var/cache/auto-upgrade-tester/ssh-key DebugBrokenScripts=yes [KVM] Virtio=True VncNum=3 SshPort=54324 ImageDir=/var/cache/auto-upgrade-tester/ CacheImageDir=/var/cache/auto-upgrade-tester/ BaseImage=%(ImageDir)s/lucid-i386.qcow2 ;SwapImage=jeos/swap.qcow2 CacheBaseImage=yes [EC2] ; Ubuntu official images: ; https://help.ubuntu.com/community/EC2StartersGuide#Getting%20the%20images ;AMI=ami-44bb5c2d ; inofficial image AMI=ami-0d729464 SSHKey=./ec2-keypair.pem ;Specify the security groups you want attached to ;the instance. For example: ;SecurityGroups = ssh,web ; Set this to "yes" if using an Ubuntu official AMI as we need to ; allow root logins ;UbuntuOfficialAMI = yes [CHROOT] Tempdir=/tmp/upgrade-tester CacheTarball=yes auto-upgrade-testing/share/profiles/auto-install-tester/pkgs_blacklist.txt0000664000000000000000000000004612076525005024422 0ustar emacspeak espeak pioneers-meta-server auto-upgrade-testing/share/profiles/auto-install-tester/pkgs.cfg0000664000000000000000000000002412076525005022306 0ustar update-manager-core auto-upgrade-testing/share/profiles/quantal-server-i386/0000775000000000000000000000000012076525005020405 5ustar auto-upgrade-testing/share/profiles/quantal-server-i386/result/0000775000000000000000000000000012076525005021723 5ustar auto-upgrade-testing/share/profiles/quantal-server-i386/known_hosts0000664000000000000000000000033612076525005022706 0ustar |1|cq+WV6AGd49L8tOwHioepyiqnLE=|GoYkoXG5Of5kB6Zo4FWyucXYJVM= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIUoJxPZ+fgX/pbWsU0siNYz19PjZXXLekPiGua8Pch+F4NA1n8gWgCxVWJ52MZnlaQgMiQNc2+0u67XOBvYGc8= auto-upgrade-testing/share/profiles/quantal-server-i386/DistUpgrade.cfg0000664000000000000000000000020312076525005023274 0ustar [DEFAULT] SourceRelease=precise TargetRelease=quantal [NonInteractive] ProfileName=quantal-server-i386 AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/quantal-server-i386/pkgs.cfg0000664000000000000000000000002312076525005022025 0ustar grub-pc python-apt auto-upgrade-testing/share/profiles/main-all/0000775000000000000000000000000012076525005016437 5ustar auto-upgrade-testing/share/profiles/main-all/result/0000775000000000000000000000000012076525005017755 5ustar auto-upgrade-testing/share/profiles/main-all/install_blacklist.cfg0000664000000000000000000000102112076525005022610 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity auto-upgrade-testing/share/profiles/main-all/DistUpgrade.cfg0000664000000000000000000000036412076525005021336 0ustar [NonInteractive] ProfileName = main-all AdditionalPkgs = pkgs.cfg PostBootstrapScript=$(AutoUpgradeTesterSharedDir)/install_all.py ;PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_all.py [KVM] VirtualRam=3072 auto-upgrade-testing/share/profiles/main-all/pkgs.cfg0000664000000000000000000000002312076525005020057 0ustar grub-pc python-apt auto-upgrade-testing/share/profiles/euca-nc/0000775000000000000000000000000012076525005016260 5ustar auto-upgrade-testing/share/profiles/euca-nc/DistUpgrade.cfg0000664000000000000000000000007612076525005021157 0ustar [NonInteractive] ProfileName=eua-nc AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/euca-nc/pkgs.cfg0000664000000000000000000000003112076525005017677 0ustar python-apt eucalyptus-nc auto-upgrade-testing/share/profiles/dapper-hardy-lucid-ubuntu/0000775000000000000000000000000012076525005021743 5ustar auto-upgrade-testing/share/profiles/dapper-hardy-lucid-ubuntu/DistUpgrade.cfg0000664000000000000000000000320212076525005024634 0ustar # # this is a dapper->hardy->lucid test image # - its cheated because the base image was dapper and then it was # *manually* upgraded to hardy, but because we cache the base # image this is ok and its a dapper->hardy->lucid upgrade from # that point on [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive [Distro] BaseMetaPkgs=ubuntu-minimal, ubuntu-standard [Aufs] ;EnableFullOverlay=yes ;EnableChrootOverlay=yes ;EnableChrootRsync=yes [Sources] From=hardy To=lucid [NonInteractive] ProfileName=dapper-hardy-lucid-ubuntu BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu ;Mirror = http://us.ec2.archive.ubuntu.com/ubuntu ;Proxy=http://192.168.1.1:3128/ ForceOverwrite=no Components=main,restricted Pockets=security,updates UpgradeFromDistOnBootstrap=true ;AddRepo=local_testing.list DpkgProgressLog=yes ResultDir=/var/cache/auto-upgrade-tester/result SSHKey=/var/cache/auto-upgrade-tester/ssh-key DebugBrokenScripts=yes [KVM] Virtio=True VncNum=1 SshPort=54322 ImageDir=/var/cache/auto-upgrade-tester/ CacheImageDir=/var/cache/auto-upgrade-tester/ BaseImage=%(ImageDir)s/dapper-i386.qcow2 ;SwapImage=jeos/swap.qcow2 CacheBaseImage=yes [EC2] ; Ubuntu official images: ; https://help.ubuntu.com/community/EC2StartersGuide#Getting%20the%20images ;AMI=ami-44bb5c2d ; inofficial image AMI=ami-0d729464 SSHKey=./ec2-keypair.pem ;Specify the security groups you want attached to ;the instance. For example: ;SecurityGroups = ssh,web ; Set this to "yes" if using an Ubuntu official AMI as we need to ; allow root logins ;UbuntuOfficialAMI = yes [CHROOT] Tempdir=/tmp/upgrade-tester CacheTarball=yes auto-upgrade-testing/share/profiles/universe-i386/0000775000000000000000000000000012076525005017274 5ustar auto-upgrade-testing/share/profiles/universe-i386/result/0000775000000000000000000000000012076525005020612 5ustar auto-upgrade-testing/share/profiles/universe-i386/install_blacklist.cfg0000664000000000000000000000110712076525005023452 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity # Breaks apache lwat # Broken on collectd kcollectd auto-upgrade-testing/share/profiles/universe-i386/DistUpgrade.cfg0000664000000000000000000000033712076525005022173 0ustar [NonInteractive] ProfileName = universe-i386 AdditionalPkgs = pkgs.cfg Components=main,restricted,universe PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_universe [KVM] VirtualRam = 3072 auto-upgrade-testing/share/profiles/universe-i386/pkgs.cfg0000664000000000000000000000004412076525005020717 0ustar grub-pc python-apt app-install-data auto-upgrade-testing/share/profiles/edubuntu/0000775000000000000000000000000012076525005016600 5ustar auto-upgrade-testing/share/profiles/edubuntu/result/0000775000000000000000000000000012076525005020116 5ustar auto-upgrade-testing/share/profiles/edubuntu/DistUpgrade.cfg0000664000000000000000000000025512076525005021476 0ustar [Sources] Components=main,restricted,universe,multiverse [NonInteractive] ProfileName = edubuntu BasePkg = edubuntu-desktop Components=main,restricted,universe,multiverse auto-upgrade-testing/share/profiles/dapper-hardy-lucid-server/0000775000000000000000000000000012076525005021727 5ustar auto-upgrade-testing/share/profiles/dapper-hardy-lucid-server/DistUpgrade.cfg0000664000000000000000000000320312076525005024621 0ustar # # this is a dapper->hardy->lucid test image # - its cheated because the base image was dapper and then it was # *manually* upgraded to hardy, but because we cache the base # image this is ok and its a dapper->hardy->lucid upgrade from # that point on [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive [Distro] BaseMetaPkgs=ubuntu-minimal, ubuntu-standard [Aufs] ;EnableFullOverlay=yes ;EnableChrootOverlay=yes ;EnableChrootRsync=yes [Sources] From=hardy To=lucid [NonInteractive] ProfileName=dapper-hardy-lucid-server BasePkg = ubuntu-standard AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu ;Mirror = http://us.ec2.archive.ubuntu.com/ubuntu ;Proxy=http://192.168.1.1:3128/ ForceOverwrite=no Components=main,restricted Pockets=security,updates UpgradeFromDistOnBootstrap=true ;AddRepo=local_testing.list DpkgProgressLog=yes ResultDir=/var/cache/auto-upgrade-tester/result SSHKey=/var/cache/auto-upgrade-tester/ssh-key DebugBrokenScripts=yes [KVM] Virtio=True VncNum=1 SshPort=54322 ImageDir=/var/cache/auto-upgrade-tester/ CacheImageDir=/var/cache/auto-upgrade-tester/ BaseImage=%(ImageDir)s/dapper-i386.qcow2 ;SwapImage=jeos/swap.qcow2 CacheBaseImage=yes [EC2] ; Ubuntu official images: ; https://help.ubuntu.com/community/EC2StartersGuide#Getting%20the%20images ;AMI=ami-44bb5c2d ; inofficial image AMI=ami-0d729464 SSHKey=./ec2-keypair.pem ;Specify the security groups you want attached to ;the instance. For example: ;SecurityGroups = ssh,web ; Set this to "yes" if using an Ubuntu official AMI as we need to ; allow root logins ;UbuntuOfficialAMI = yes [CHROOT] Tempdir=/tmp/upgrade-tester CacheTarball=yes auto-upgrade-testing/share/profiles/main-all-amd64/0000775000000000000000000000000012076525005017350 5ustar auto-upgrade-testing/share/profiles/main-all-amd64/result/0000775000000000000000000000000012076525005020666 5ustar auto-upgrade-testing/share/profiles/main-all-amd64/install_blacklist.cfg0000664000000000000000000000102212076525005023522 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity auto-upgrade-testing/share/profiles/main-all-amd64/DistUpgrade.cfg0000664000000000000000000000041512076525005022244 0ustar [NonInteractive] ProfileName = main-all-amd64 AdditionalPkgs = pkgs.cfg PostBootstrapScript=/usr/share/pyshared/AutoUpgradeTester/install_all.py ;PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_all.py [KVM] Arch=amd64 VirtualRam=3072 auto-upgrade-testing/share/profiles/main-all-amd64/pkgs.cfg0000664000000000000000000000002312076525005020770 0ustar python-apt grub-pc auto-upgrade-testing/share/profiles/lts-kubuntu/0000775000000000000000000000000012076525005017242 5ustar auto-upgrade-testing/share/profiles/lts-kubuntu/result/0000775000000000000000000000000012076525005020560 5ustar auto-upgrade-testing/share/profiles/lts-kubuntu/DistUpgrade.cfg0000664000000000000000000000014212076525005022133 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName=lts-kubuntu BasePkg = kubuntu-desktop auto-upgrade-testing/share/profiles/lts-mythbuntu/0000775000000000000000000000000012076525005017604 5ustar auto-upgrade-testing/share/profiles/lts-mythbuntu/DistUpgrade.cfg0000664000000000000000000000025612076525005022503 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName=lts-mythbuntu BasePkg = mythbuntu-desktop Components=main,restricted,universe,multiverse Pockets=security,updates auto-upgrade-testing/share/profiles/lts-main-all/0000775000000000000000000000000012076525005017237 5ustar auto-upgrade-testing/share/profiles/lts-main-all/removal_blacklist.cfg0000664000000000000000000000035412076525005023417 0ustar # blacklist of packages that should never be removed ubuntu-standard ubuntu-minimal ubuntu-desktop kubuntu-desktop edubuntu-desktop gobuntu-desktop # never remove nvidia-glx and friends ^nvidia-glx$ ^nvidia-glx-new$ ^nvidia-glx-legacy$ auto-upgrade-testing/share/profiles/lts-main-all/install_blacklist.cfg0000664000000000000000000000144112076525005023416 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity # No need for so many kernels linux-image-.* # Failed to install bacula-director-mysql dovecot-common rabbitmq-server # cloud/ec2 no fun cloud-init ec2-init linux-image-ec2 linux-image-2.6.31-302-ec2 # not installable on a regular machine ltsp-client ltsp-client-core auto-upgrade-testing/share/profiles/lts-main-all/DistUpgrade.cfg0000664000000000000000000000043712076525005022137 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName = lts-main-all AdditionalPkgs = pkgs.cfg PostBootstrapScript=/usr/share/pyshared/AutoUpgradeTester/install_all.py ;PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_all.py [KVM] VirtualRam=3072 auto-upgrade-testing/share/profiles/lts-main-all/DistUpgrade.cfg.dapper0000664000000000000000000000312312076525005023404 0ustar [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive # Distro contains global information about the upgrade [Distro] # the meta-pkgs we support MetaPkgs=ubuntu-desktop, kubuntu-desktop, edubuntu-desktop, xubuntu-desktop BaseMetaPkgs=ubuntu-minimal, ubuntu-standard PostUpgradePurge=xorg-common, libgl1-mesa Demotions=demoted.cfg RemoveEssentialOk=sysvinit RemovalBlacklistFile=removal_blacklist.cfg # information about the individual meta-pkgs [ubuntu-desktop] KeyDependencies=gdm, gnome-panel, ubuntu-artwork # those pkgs will be marked remove right after the distUpgrade in the cache PostUpgradeRemove=xchat, xscreensaver [kubuntu-desktop] KeyDependencies=kdm, kicker, kubuntu-artwork-usplash # those packages are marked as obsolete right after the upgrade ForcedObsoletes=ivman [edubuntu-desktop] KeyDependencies=edubuntu-artwork, tuxpaint [xubuntu-desktop] KeyDependencies=xubuntu-artwork-usplash, xubuntu-default-settings, xfce4 [Files] BackupExt=distUpgrade [Sources] From=dapper To=hardy ValidOrigin=Ubuntu ValidMirrors = mirrors.cfg [Network] MaxRetries=3 [PreRequists] Packages=release-upgrader-apt,release-upgrader-dpkg SourcesList=prerequists-sources.list [NonInteractive] ProfileName = main-all BasePkg = ubuntu-standard AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu Proxy=http://192.168.1.1:3128/ ForceOverwrite=yes CacheTarball=yes PostBootstrapScript=install_all.py Components=main,restricted Pockets=security,updates BaseImage=jeos/dapper-i386.qcow2 CacheBaseImage=yes SwapImage=jeos/swap.qcow2 UpgradeFromDistOnBootstrap=true SSHKey=ssh-key ReadReboot=yesauto-upgrade-testing/share/profiles/lts-main-all/pkgs.cfg0000664000000000000000000000005112076525005020660 0ustar python-apt python-gnupginterface grub-pc auto-upgrade-testing/share/profiles/lts-main-all/prerequists-sources.list0000664000000000000000000000053512076525005024206 0ustar # sources.list fragment for pre-requists (one with countrymirror, one fallback) deb http://archive.ubuntu.com/ubuntu dapper-backports main/debian-installer #deb http://archive.ubuntu.com/ubuntu feisty-backports main/debian-installer # below is just for testing #deb http://archive.dogfood.launchpad.net/ubuntu feisty-backports main/debian-installer auto-upgrade-testing/share/profiles/quantal-desktop-amd64/0000775000000000000000000000000012076525005020772 5ustar auto-upgrade-testing/share/profiles/quantal-desktop-amd64/result/0000775000000000000000000000000012076525005022310 5ustar auto-upgrade-testing/share/profiles/quantal-desktop-amd64/DistUpgrade.cfg0000664000000000000000000000026112076525005023665 0ustar [DEFAULT] SourceRelease=precise TargetRelease=quantal [NonInteractive] ProfileName = quantal-desktop-amd64 BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/quantal-desktop-amd64/pkgs.cfg0000664000000000000000000000001012076525005022406 0ustar grub-pc auto-upgrade-testing/share/profiles/server-tasks/0000775000000000000000000000000012076525005017376 5ustar auto-upgrade-testing/share/profiles/server-tasks/DistUpgrade.cfg0000664000000000000000000000010412076525005022265 0ustar [NonInteractive] ProfileName=server-tasks AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/server-tasks/pkgs.cfg0000664000000000000000000000021612076525005021022 0ustar grub-pc python-apt python-gnupginterface dns-server^ lamp-server^ mail-server^ openssh-server^ postgresql-server^ print-server^ samba-server^ auto-upgrade-testing/share/profiles/lts-server/0000775000000000000000000000000012076525005017053 5ustar auto-upgrade-testing/share/profiles/lts-server/local_testing.list0000664000000000000000000000010412076525005022572 0ustar deb http://ppa.launchpad.net/mvo/apt-lucid-chris/ubuntu lucid main auto-upgrade-testing/share/profiles/lts-server/DistUpgrade.cfg0000664000000000000000000000017112076525005021746 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName=lts-server AdditionalPkgs = pkgs.cfg ;UseUpgraderFromBzr=trueauto-upgrade-testing/share/profiles/lts-server/DistUpgrade.cfg.dapper0000664000000000000000000000245612076525005023230 0ustar [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive Depends=python-gnupginterface # Distro contains global information about the upgrade [Distro] # the meta-pkgs we support MetaPkgs=ubuntu-standard BaseMetaPkgs=ubuntu-minimal Demotions=demotions.cfg RemoveEssentialOk=sysvinit AllowUnauthenticated=yes [Files] BackupExt=distUpgrade [ubuntu-standard] KeyDependencies=w3m, wget [Sources] From=dapper To=hardy ValidOrigin=Ubuntu ValidMirrors = mirrors.cfg [Network] MaxRetries=3 [PreRequists] Packages=release-upgrader-apt,release-upgrader-dpkg SourcesList=prerequists-sources.dapper.list SourcesList-ia64=prerequists-sources.dapper-ports.list SourcesList-hppa=prerequists-sources.dapper-ports.list [NonInteractive] ProfileName=server BasePkg = ubuntu-standard AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu Proxy=http://192.168.1.1:3128/ ForceOverwrite=no SSHKey=ssh-key BaseImage=jeos/dapper-i386.qcow2 SwapImage=jeos/swap.qcow2 Components=main,restricted Pockets=security,updates UpgradeFromDistOnBoostrap=true CacheBaseImage=yes RealReboot=yes ; WARNING: if AddRepo is used, remember to set Distro/AllowUnauthenticted too ;AddRepo=local_testing.list ;PreRequistsFiles=backports/release-upgrader-apt_0.7.9ubuntu1_i386.udeb, backports/release-upgrader-dpkg_1.14.5ubuntu11.6_i386.udeb auto-upgrade-testing/share/profiles/lts-server/pkgs.cfg0000664000000000000000000000005112076525005020474 0ustar grub-pc python-apt python-gnupginterface auto-upgrade-testing/share/profiles/ubuntu-amd64/0000775000000000000000000000000012076525005017200 5ustar auto-upgrade-testing/share/profiles/ubuntu-amd64/result/0000775000000000000000000000000012076525005020516 5ustar auto-upgrade-testing/share/profiles/ubuntu-amd64/DistUpgrade.cfg0000664000000000000000000000016112076525005022072 0ustar [NonInteractive] ProfileName = ubuntu-amd64 BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/ubuntu-amd64/pkgs.cfg0000664000000000000000000000001012076525005020614 0ustar grub-pc auto-upgrade-testing/share/profiles/override.cfg.d/0000775000000000000000000000000012076525005017544 5ustar auto-upgrade-testing/share/profiles/override.cfg.d/global.cfg0000664000000000000000000000042012076525005021461 0ustar # global override, this will override any configuration from the # defaults profile directory and from the release upgrader configuration # # It is required to force non-interactive upgrade mode but can be used # for more too [View] View=DistUpgradeViewNonInteractive auto-upgrade-testing/share/profiles/quantal-server-tasks-i386/0000775000000000000000000000000012076525005021530 5ustar auto-upgrade-testing/share/profiles/quantal-server-tasks-i386/DistUpgrade.cfg0000664000000000000000000000021012076525005024415 0ustar [DEFAULT] SourceRelease=precise TargetRelease=quantal [NonInteractive] ProfileName=quantal-server-tasks-i386 AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/quantal-server-tasks-i386/pkgs.cfg0000664000000000000000000000021612076525005023154 0ustar grub-pc python-apt python-gnupginterface dns-server^ lamp-server^ mail-server^ openssh-server^ postgresql-server^ print-server^ samba-server^ auto-upgrade-testing/share/profiles/server-amd64/0000775000000000000000000000000012076525005017164 5ustar auto-upgrade-testing/share/profiles/server-amd64/DistUpgrade.cfg0000664000000000000000000000012712076525005022060 0ustar [NonInteractive] ProfileName=server-amd64 AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/server-amd64/pkgs.cfg0000664000000000000000000000002312076525005020604 0ustar grub-pc python-apt auto-upgrade-testing/share/profiles/xubuntu/0000775000000000000000000000000012076525005016457 5ustar auto-upgrade-testing/share/profiles/xubuntu/result/0000775000000000000000000000000012076525005017775 5ustar auto-upgrade-testing/share/profiles/xubuntu/DistUpgrade.cfg0000664000000000000000000000014512076525005021353 0ustar [NonInteractive] ProfileName = xubuntu BasePkg = xubuntu-desktop Components=main,restricted,universe auto-upgrade-testing/share/profiles/ubuntu/0000775000000000000000000000000012076525005016267 5ustar auto-upgrade-testing/share/profiles/ubuntu/result/0000775000000000000000000000000012076525005017605 5ustar auto-upgrade-testing/share/profiles/ubuntu/DistUpgrade.cfg0000664000000000000000000000013112076525005021156 0ustar [NonInteractive] ProfileName = ubuntu BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/ubuntu/pkgs.cfg0000664000000000000000000000001012076525005017703 0ustar grub-pc auto-upgrade-testing/share/profiles/lts-ubuntu/0000775000000000000000000000000012076525005017067 5ustar auto-upgrade-testing/share/profiles/lts-ubuntu/DistUpgrade.cfg0000664000000000000000000000045612076525005021770 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName=lts-ubuntu BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg PostBootstrapData = /usr/share/pyshared/AutoUpgradeTester/prepare_lts_user PostBootstrapScript = /usr/share/pyshared/AutoUpgradeTester/prepare_lts_desktop ;UseUpgraderFromBzr=true auto-upgrade-testing/share/profiles/lts-ubuntu/DistUpgrade.cfg.dapper0000664000000000000000000000335712076525005023245 0ustar [View] #View=DistUpgradeViewGtk View=DistUpgradeViewNonInteractive # Distro contains global information about the upgrade [Distro] # the meta-pkgs we support MetaPkgs=ubuntu-desktop, kubuntu-desktop, edubuntu-desktop, xubuntu-desktop BaseMetaPkgs=ubuntu-minimal, ubuntu-standard PostUpgradePurge=xorg-common, libgl1-mesa Demotions=demoted.cfg RemoveEssentialOk=sysvinit RemovalBlacklistFile=removal_blacklist.cfg AllowUnauthenticated=yes PostInstallScripts=/usr/lib/udev/migrate-fstab-to-uuid.sh # information about the individual meta-pkgs [ubuntu-desktop] KeyDependencies=gdm, gnome-panel, ubuntu-artwork # those pkgs will be marked remove right after the distUpgrade in the cache PostUpgradeRemove=xchat, xscreensaver [kubuntu-desktop] KeyDependencies=kdm, kicker, kubuntu-artwork-usplash # those packages are marked as obsolete right after the upgrade ForcedObsoletes=ivman [edubuntu-desktop] KeyDependencies=edubuntu-artwork, tuxpaint [xubuntu-desktop] KeyDependencies=xubuntu-artwork-usplash, xubuntu-default-settings, xfce4 [Files] BackupExt=distUpgrade [PreRequists] Packages=release-upgrader-apt,release-upgrader-dpkg SourcesList=prerequists-sources.dapper.list [Sources] From=dapper To=hardy ValidOrigin=Ubuntu ValidMirrors = mirrors.cfg [Network] MaxRetries=3 [NonInteractive] ProfileName = ubuntu BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg Mirror = http://archive.ubuntu.com/ubuntu Proxy=http://192.168.1.1:3128/ ForceOverwrite=yes Components=main,restricted Pockets=security,updates SSHKey=ssh-key BaseImage=jeos/dapper-i386.qcow2 CacheBaseImage=yes SwapImage=jeos/swap.qcow2 UpgradeFromDistOnBootstrap=true WorkaroundNetworkManager=true ; WARNING: if AddRepo is used, remember to set Distro/AllowUnauthenticted too AddRepo=local_testing.list auto-upgrade-testing/share/profiles/lts-ubuntu/pkgs.cfg0000664000000000000000000000004712076525005020515 0ustar ubuntu-minimal ubuntu-standard grub-pc auto-upgrade-testing/share/profiles/server/0000775000000000000000000000000012076525005016253 5ustar auto-upgrade-testing/share/profiles/server/result/0000775000000000000000000000000012076525005017571 5ustar auto-upgrade-testing/share/profiles/server/known_hosts0000664000000000000000000000033612076525005020554 0ustar |1|cq+WV6AGd49L8tOwHioepyiqnLE=|GoYkoXG5Of5kB6Zo4FWyucXYJVM= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIUoJxPZ+fgX/pbWsU0siNYz19PjZXXLekPiGua8Pch+F4NA1n8gWgCxVWJ52MZnlaQgMiQNc2+0u67XOBvYGc8= auto-upgrade-testing/share/profiles/server/DistUpgrade.cfg0000664000000000000000000000007712076525005021153 0ustar [NonInteractive] ProfileName=server AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/server/pkgs.cfg0000664000000000000000000000002312076525005017673 0ustar grub-pc python-apt auto-upgrade-testing/share/profiles/lts-universe-amd64/0000775000000000000000000000000012076525005020316 5ustar auto-upgrade-testing/share/profiles/lts-universe-amd64/result/0000775000000000000000000000000012076525005021634 5ustar auto-upgrade-testing/share/profiles/lts-universe-amd64/install_blacklist.cfg0000664000000000000000000000121512076525005024474 0ustar # jaunty: endless loop with DEBIAN_FRONTEND=noninteractive moodle # has a funny "can not be upgraded automatically" policy # see debian #368226 quagga # not installable on a regular machine (preinst error) ltsp-client # gwenview-i18n has some file conflicts gwenview-i18n # ipppd needs MAKEDEV ipppd # cmake has incorrect emacs dependencies cmake # cluster manager hangs on shutdown cman # Conflicts/uninstallable packages in Oneiric libgladeui-doc mythes-it amavisd-new grub-legacy-ec2 # Only useful on livecd casper ubiquity # Breaks apache lwat # Broken on collectd kcollectd # Failed to install on lucid global likewise-open likewise-open-gui auto-upgrade-testing/share/profiles/lts-universe-amd64/DistUpgrade.cfg0000664000000000000000000000042012076525005023206 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName = lts-universe-amd64 AdditionalPkgs = pkgs.cfg Components=main,restricted,universe PostBootstrapScript=/home/upgrade-tester/update-manager/AutoUpgradeTester/install_universe [KVM] Arch = amd64 VirtualRam = 3072 auto-upgrade-testing/share/profiles/lts-universe-amd64/pkgs.cfg0000664000000000000000000000004412076525005021741 0ustar grub-pc python-apt app-install-data auto-upgrade-testing/share/profiles/lubuntu/0000775000000000000000000000000012076525005016443 5ustar auto-upgrade-testing/share/profiles/lubuntu/DistUpgrade.cfg0000664000000000000000000000014512076525005021337 0ustar [NonInteractive] ProfileName = lubuntu BasePkg = lubuntu-desktop Components=main,restricted,universe auto-upgrade-testing/share/profiles/defaults.cfg.d/0000775000000000000000000000000012076525005017534 5ustar auto-upgrade-testing/share/profiles/defaults.cfg.d/defaults.cfg0000664000000000000000000000302712076525005022026 0ustar # global defaults, override as needed in the indivual configuration # files # [DEFAULT] AutoUpgradeTesterBaseDir=/var/cache AutoUpgradeTesterSharedDir=/home/upgrade-tester/update-manager/AutoUpgradeTester SourceRelease=precise TargetRelease=quantal [Distro] BaseMetaPkgs=ubuntu-minimal, ubuntu-standard [Sources] From=%(SourceRelease)s To=%(TargetRelease)s [NonInteractive] BasePkg = ubuntu-standard Mirror = http://archive.ubuntu.com/ubuntu ForceOverwrite=no Components=main,restricted Pockets=security,updates UpgradeFromDistOnBootstrap=false DpkgProgressLog=no ResultDir=%(AutoUpgradeTesterBaseDir)s/auto-upgrade-tester/result SSHKey=%(AutoUpgradeTesterBaseDir)s/auto-upgrade-tester/ssh-key DebugBrokenScripts=yes UseUpgraderFromBzr=false ;AddRepo=local_testing.list ;DebconfLog=/var/log/dist-upgrade/debconf.log [KVM] Virtio=True Arch=i386 ImageDir=%(AutoUpgradeTesterBaseDir)s/auto-upgrade-tester/ CacheImageDir=%(AutoUpgradeTesterBaseDir)s/auto-upgrade-tester/ BaseImage=%(ImageDir)s/%(SourceRelease)s-%(Arch)s.qcow2 CacheBaseImage=yes VncNum=1 SshPort=54322 VirtualRam=1536 RootSize=80000 [EC2] ; Ubuntu official images: ; https://help.ubuntu.com/community/EC2StartersGuide#Getting%20the%20images ;AMI=ami-44bb5c2d ; inofficial image AMI=ami-0d729464 SSHKey=./ec2-keypair.pem ;Specify the security groups you want attached to ;the instance. For example: ;SecurityGroups = ssh,web ; Set this to "yes" if using an Ubuntu official AMI as we need to ; allow root logins ;UbuntuOfficialAMI = yes [CHROOT] Tempdir=/tmp/upgrade-tester CacheTarball=yes auto-upgrade-testing/share/profiles/quantal-desktop-i386/0000775000000000000000000000000012076525005020550 5ustar auto-upgrade-testing/share/profiles/quantal-desktop-i386/result/0000775000000000000000000000000012076525005022066 5ustar auto-upgrade-testing/share/profiles/quantal-desktop-i386/DistUpgrade.cfg0000664000000000000000000000023612076525005023445 0ustar [DEFAULT] SourceRelease=precise TargetRelease=quantal [NonInteractive] ProfileName = quantal-desktop-i386 BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/quantal-desktop-i386/pkgs.cfg0000664000000000000000000000001012076525005022164 0ustar grub-pc auto-upgrade-testing/share/profiles/euca-cloud/0000775000000000000000000000000012076525005016766 5ustar auto-upgrade-testing/share/profiles/euca-cloud/DistUpgrade.cfg0000664000000000000000000000010212076525005021653 0ustar [NonInteractive] ProfileName=eua-cloud AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/euca-cloud/pkgs.cfg0000664000000000000000000000011212076525005020405 0ustar python-apt eucalyptus-cc eucalyptus-cloud eucalyptus-walrus eucalyptus-sc auto-upgrade-testing/share/profiles/lts-ubuntu-amd64/0000775000000000000000000000000012076525005020000 5ustar auto-upgrade-testing/share/profiles/lts-ubuntu-amd64/DistUpgrade.cfg0000664000000000000000000000043712076525005022700 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName=lts-ubuntu-amd64 BasePkg = ubuntu-desktop AdditionalPkgs = pkgs.cfg PostBootstrapData = $(AutoUpgradeTesterSharedDir)/prepare_lts_user PostBootstrapScript = $(AutoUpgradeTesterSharedDir)/prepare_lts_desktop [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/lts-ubuntu-amd64/pkgs.cfg0000664000000000000000000000004712076525005021426 0ustar ubuntu-minimal ubuntu-standard grub-pc auto-upgrade-testing/share/profiles/lts-server-tasks/0000775000000000000000000000000012076525005020176 5ustar auto-upgrade-testing/share/profiles/lts-server-tasks/DistUpgrade.cfg0000664000000000000000000000015112076525005023067 0ustar [DEFAULT] SourceRelease=lucid [NonInteractive] ProfileName = lts-server-tasks AdditionalPkgs = pkgs.cfg auto-upgrade-testing/share/profiles/lts-server-tasks/pkgs.cfg0000664000000000000000000000021612076525005021622 0ustar grub-pc python-apt python-gnupginterface dns-server^ lamp-server^ mail-server^ openssh-server^ postgresql-server^ print-server^ samba-server^ auto-upgrade-testing/share/profiles/server-tasks-amd64/0000775000000000000000000000000012076525005020307 5ustar auto-upgrade-testing/share/profiles/server-tasks-amd64/DistUpgrade.cfg0000664000000000000000000000013412076525005023201 0ustar [NonInteractive] ProfileName=server-tasks-amd64 AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/server-tasks-amd64/pkgs.cfg0000664000000000000000000000020512076525005021731 0ustar python-apt python-gnupginterface dns-server^ lamp-server^ mail-server^ openssh-server^ postgresql-server^ print-server^ samba-server^auto-upgrade-testing/share/profiles/quantal-server-amd64/0000775000000000000000000000000012076525005020627 5ustar auto-upgrade-testing/share/profiles/quantal-server-amd64/DistUpgrade.cfg0000664000000000000000000000022612076525005023523 0ustar [DEFAULT] SourceRelease=precise TargetRelease=quantal [NonInteractive] ProfileName=quantal-server-amd64 AdditionalPkgs = pkgs.cfg [KVM] Arch=amd64 auto-upgrade-testing/share/profiles/quantal-server-amd64/pkgs.cfg0000664000000000000000000000002312076525005022247 0ustar grub-pc python-apt auto-upgrade-testing/share/profiles/python-all/0000775000000000000000000000000012076525005017034 5ustar auto-upgrade-testing/share/profiles/python-all/DistUpgrade.cfg0000664000000000000000000000025512076525005021732 0ustar [NonInteractive] ProfileName=python-all BasePkg = ubuntu-standard AdditionalPkgs = pkgs.cfg PostBootstrapScript=/usr/share/pyshared/AutoUpgradeTester/install_all-python.py auto-upgrade-testing/share/profiles/python-all/pkgs.cfg0000664000000000000000000000002312076525005020454 0ustar grub-pc python-apt auto-upgrade-testing/AutoUpgradeTester/0000775000000000000000000000000012076525005015427 5ustar auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackendSimulate.py0000664000000000000000000000161612076525005023210 0ustar # UpgradeTestBackendSimulate.py # # test backend # from __future__ import absolute_import, print_function import tempfile from AutoUpgradeTester.UpgradeTestBackend import UpgradeTestBackend class UpgradeTestBackendSimulate(UpgradeTestBackend): def __init__(self, profiledir, resultdir=""): tmpdir = tempfile.mkdtemp() super(UpgradeTestBackendSimulate, self).__init__(profiledir, resultdir=tmpdir) def installPackages(self, pkgs): print("simulate installing packages: %s" % ",".join(pkgs)) def bootstrap(self): " bootstaps a pristine install" print("simulate running bootstrap") return True def upgrade(self): " upgrade a given install " print("simulate running upgrade") return True def test(self): " test if the upgrade was successful " print("running post upgrade test") return True auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackendSSH.py0000664000000000000000000002230012076525005022053 0ustar # abstract backend that is based around ssh login from __future__ import absolute_import, print_function from AutoUpgradeTester.UpgradeTestBackend import UpgradeTestBackend import glob import logging import os import subprocess import time class UpgradeTestBackendSSH(UpgradeTestBackend): " abstract backend that works with ssh " def __init__(self, profile): UpgradeTestBackend.__init__(self, profile) self.profiledir = os.path.dirname(profile) # get ssh key name self.ssh_key = os.path.abspath( self.config.getWithDefault( "NonInteractive", "SSHKey", "/var/cache/auto-upgrade-tester/ssh-key") ) if not os.path.exists(self.ssh_key): print("Creating key: %s" % self.ssh_key) subprocess.call(["ssh-keygen","-N","","-f",self.ssh_key]) def login(self): " run a shell in the image " print("login") self.start() ret = self._runInImage(["/bin/sh"]) if ret != 0: logging.warn("_runInImage returned: %s" % ret) self.stop() def ping(self, user="root"): " check if the instance is ready " ret = self._runInImageAsUser(user, ["/bin/true"]) return (ret == 0) def _copyToImage(self, fromF, toF, recursive=False): "copy a file (or a list of files) to the given toF image location" cmd = ["scp", "-P", self.ssh_port, "-q","-q", # shut it up "-i",self.ssh_key, "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=%s" % os.path.dirname( self.profile)+"/known_hosts" ] if recursive: cmd.append("-r") # we support both single files and lists of files if isinstance(fromF,list): cmd += fromF else: cmd.append(fromF) cmd.append("root@%s:%s" % (self.ssh_hostname, toF)) #print(cmd) ret = subprocess.call(cmd) return ret def _copyFromImage(self, fromF, toF): "copy a file from the given fromF image location" cmd = ["scp", "-P",self.ssh_port, "-q","-q", # shut it up "-i",self.ssh_key, "-o", "StrictHostKeyChecking=no", "-o", "UserKnownHostsFile=%s" % os.path.dirname(self.profile)+"/known_hosts", "root@%s:%s" % (self.ssh_hostname, fromF), toF ] #print(cmd) ret = subprocess.call(cmd) return ret def _runInImage(self, command, **kwargs): ret = self._runInImageAsUser("root", command, **kwargs) return ret def _runInImageAsUser(self, user, command, **kwargs): "run a given command in the image" # ssh -l root -p 54321 localhost -i profile/server/ssh_key # -o StrictHostKeyChecking=no ret = subprocess.call(["ssh", "-tt", "-l", user, "-p",self.ssh_port, self.ssh_hostname, "-q","-q", # shut it up "-i",self.ssh_key, "-o", "StrictHostKeyChecking=no", "-o", "BatchMode=yes", "-o", "UserKnownHostsFile=%s" % os.path.dirname(self.profile)+"/known_hosts", ]+command, universal_newlines=True, **kwargs) return ret def installPackages(self, pkgs): " install additional pkgs (list) into the vm before the upgrade " if not pkgs: return True self.start() self._runInImage(["apt-get","update"]) ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install", "--reinstall", "-y"]+pkgs) self.stop() return (ret == 0) def _copyUpgraderFilesFromBzrCheckout(self): " copy upgrader files from a bzr checkout " print("copy upgrader into image") # copy the upgrade into target+/upgrader-tester/ files = [] self._runInImage(["mkdir","-p","/upgrade-tester","/etc/update-manager/release-upgrades.d"]) for f in glob.glob("%s/*" % self.upgradefilesdir): if not os.path.isdir(f): files.append(f) elif os.path.islink(f): print("Copying link '%s' to image " % f) self._copyToImage(f, "/upgrade-tester", recursive=True) self._copyToImage(files, "/upgrade-tester") # and any other cfg files for f in glob.glob(os.path.dirname(self.profile)+"/*.cfg"): if (os.path.isfile(f) and not os.path.basename(f).startswith("DistUpgrade.cfg")): print("Copying '%s' to image " % f) self._copyToImage(f, "/upgrade-tester") # base-installer bi="%s/base-installer" % self.upgradefilesdir print("Copying '%s' to image" % bi) self._copyToImage(bi, "/upgrade-tester/", recursive=True) # copy the patches pd="%s/patches" % self.upgradefilesdir print("Copying '%s' to image" % pd) self._copyToImage(pd, "/upgrade-tester/", recursive=True) # and prereq lists prereq = self.config.getWithDefault("PreRequists","SourcesList",None) if prereq is not None: prereq = os.path.join(os.path.dirname(self.profile),prereq) print("Copying '%s' to image" % prereq) self._copyToImage(prereq, "/upgrade-tester") def _runBzrCheckoutUpgrade(self, cmd_prefix): # start the upgrader print("running the upgrader now") # this is to support direct copying of backport udebs into the # qemu image - useful for testing backports without having to # push them into the archive upgrader_args = "" upgrader_env = "" backports = self.config.getlist("NonInteractive", "PreRequistsFiles") if backports: self._runInImage(["mkdir -p /upgrade-tester/backports"]) for f in backports: print("Copying %s" % os.path.basename(f)) self._copyToImage(f, "/upgrade-tester/backports/") self._runInImage(["(cd /upgrade-tester/backports ; dpkg-deb -x %s . )" % os.path.basename(f)]) upgrader_args = " --have-prerequists" upgrader_env = "LD_LIBRARY_PATH=/upgrade-tester/backports/usr/lib PATH=/upgrade-tester/backports/usr/bin:$PATH PYTHONPATH=/upgrade-tester/backports//usr/lib/python$(python -c 'import sys; print(\"%s.%s\" % (sys.version_info[0], sys.version_info[1]))')/site-packages/ " ret = self._runInImage(cmd_prefix+["(cd /upgrade-tester/ ; " "%s./dist-upgrade.py %s)" % (upgrader_env, upgrader_args)]) return ret def test(self): # - generate diff of upgrade vs fresh install # ... #self.genDiff() self.start() # check for crashes try: self._runInImage(['chmod', '744', '/var/crash/*.crash']) self._copyFromImage("/var/crash/*.crash", self.resultdir) except Exception as exc: print('WARNING: Failed to copy crash files: %s' % exc) crashfiles = glob.glob(self.resultdir+"/*.crash") # run stuff in post_upgrade_tests dir ok = True results = [] for script in glob.glob(self.post_upgrade_tests_dir+"*"): if not os.access(script, os.X_OK): continue result = {'name':os.path.basename(script), 'result':'pass', 'time':0, 'message':'' } start_time = time.time() logging.info("running '%s' post_upgrade_test" % script) self._copyToImage(script, "/tmp/") ret = self._runInImage(["/tmp/%s" % os.path.basename(script)]) if ret != 0: print("WARNING: post_upgrade_test '%s' failed" % script) ok = False log=open(self.resultdir+"/test-%s.FAIL" % os.path.basename(script), "w") log.write("FAIL") result['result'] = 'fail' result['message'] = "post_upgrade_test '%s' failed" % script result['time'] = time.time() - start_time results.append(result) # check for conffiles (the copy is done via a post upgrade script) self._copyFromImage("/tmp/*.dpkg-dist", self.resultdir) # Collect debconf prompts generated by debconf_test.py script self._copyFromImage("/tmp/debconf_*.log", self.resultdir) # Collect result of obsolete config file checks self._copyFromImage("/tmp/obsolete_conffiles.log", self.resultdir) # Collect results of python import checks self._copyFromImage('/tmp/test_python_import*', self.resultdir) self.resultsToJunitXML(results, os.path.join(self.resultdir, 'results.xml')) self.stop() if len(crashfiles) > 0: print("WARNING: crash files detected on the upgrade") print(crashfiles) return False return ok auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackendChroot.py0000664000000000000000000003052212076525005022661 0ustar from __future__ import absolute_import, print_function import sys import os import warnings warnings.filterwarnings("ignore", "apt API not stable yet", FutureWarning) from AutoUpgradeTester.UpgradeTestBackend import UpgradeTestBackend import tempfile import subprocess import shutil import glob try: import configparser configparser # pyflakes except ImportError: import ConfigParser as configparser class UpgradeTestBackendChroot(UpgradeTestBackend): diverts = ["/usr/sbin/mkinitrd", "/sbin/modprobe", "/usr/sbin/invoke-rc.d", # install-info has a locking problem quite often "/usr/sbin/install-info", "/sbin/start-stop-daemon"] def __init__(self, profile): UpgradeTestBackend.__init__(self, profile) self.tarball = None def _umount(self, chrootdir): umount_list = [] for line in open("/proc/mounts"): (dev, mnt, fs, options, d, p) = line.split() if mnt.startswith(chrootdir): umount_list.append(mnt) # now sort and umount by reverse length (to ensure # we umount /sys/fs/binfmt_misc before /sys) umount_list.sort(key=len) umount_list.reverse() # do the list for mpoint in umount_list: print("Umount '%s'" % mpoint) os.system("umount %s" % mpoint) def login(self): d = self._unpackToTmpdir(self.tarball) print("logging into: '%s'" % d) self._runInChroot(d, ["/bin/sh"]) print("Cleaning up") if d: shutil.rmtree(d) def _runInChroot(self, chrootdir, command, cmd_options=[]): print("running: ", command) print("in: ", chrootdir) pid = os.fork() if pid == 0: os.chroot(chrootdir) os.chdir("/") os.system("mount -t devpts devpts /dev/pts") os.system("mount -t sysfs sysfs /sys") os.system("mount -t proc proc /proc") os.system("mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc") env = os.environ env["DEBIAN_FRONTEND"] = "noninteractive" os.execve(command[0], command, env) else: print("Parent: waiting for %s" % pid) (id, exitstatus) = os.waitpid(pid, 0) self._umount(chrootdir) return exitstatus def _runApt(self, tmpdir, command, cmd_options=[]): ret = self._runInChroot(tmpdir, ["/usr/bin/apt-get", command]+self.apt_options+cmd_options) return ret def installPackages(self, pkgs): print("installPackages: ", pkgs) if not pkgs: return True res = self._runApt(self.tmpdir, "install", pkgs) return res == 0 def _tryRandomPkgInstall(self, amount): " install 'amount' packages randomly " self._runApt(self.tmpdir,"install",["python2.4-apt", "python-apt"]) shutil.copy("%s/randomInst.py",self.tmpdir+"/tmp") ret = subprocess.call(["chroot",self.tmpdir,"/tmp/randomInst.py","%s" % amount]) print(ret) def _cacheDebs(self, tmpdir): # see if the debs should be cached if self.cachedir: print("Caching debs") for f in glob.glob(tmpdir+"/var/cache/apt/archives/*.deb"): if not os.path.exists(self.cachedir+"/"+os.path.basename(f)): try: shutil.copy(f,self.cachedir) except IOError as e: print("Can't copy '%s' (%s)" % (f, e)) def _getTmpDir(self): tmpdir = self.config.getWithDefault("CHROOT","Tempdir",None) if tmpdir is None: tmpdir = tempfile.mkdtemp() else: if os.path.exists(tmpdir): self._umount(tmpdir) shutil.rmtree(tmpdir) os.makedirs(tmpdir) return tmpdir def bootstrap(self,outfile=None): " bootstaps a pristine fromDist tarball" if not outfile: outfile = os.path.dirname(self.profile) + "/dist-upgrade-%s.tar.gz" % self.fromDist outfile = os.path.abspath(outfile) self.tarball = outfile # don't bootstrap twice if this is something we can cache try: if (self.config.getboolean("CHROOT","CacheTarball") and os.path.exists(self.tarball) ): self.tmpdir = self._unpackToTmpdir(self.tarball) if not self.tmpdir: print("Error extracting tarball") return False return True except configparser.NoOptionError: pass # bootstrap! self.tmpdir = tmpdir = self._getTmpDir() print("tmpdir is %s" % tmpdir) print("bootstrapping to %s" % outfile) ret = subprocess.call(["debootstrap", self.fromDist, tmpdir, self.config.get("NonInteractive","Mirror")]) print("debootstrap returned: %s" % ret) if ret != 0: return False print("diverting") self._dpkgDivert(tmpdir) # create some minimal device node print("Creating some devices") os.system("(cd %s/dev ; echo $PWD; ./MAKEDEV null)" % tmpdir) #self._runInChroot(tmpdir, ["/bin/mknod","/dev/null","c","1","3"]) # set a hostname shutil.copy("/etc/hostname","%s/etc/hostanme" % tmpdir) # copy the stuff from toChroot/ if os.path.exists("./toChroot/"): os.chdir("toChroot/") for (dirpath, dirnames, filenames) in os.walk("."): for name in filenames: if not os.path.exists(os.path.join(tmpdir,dirpath,name)): shutil.copy(os.path.join(dirpath,name), os.path.join(tmpdir,dirpath,name)) os.chdir("..") # write new sources.list if (self.config.has_option("NonInteractive","Components") and self.config.has_option("NonInteractive","Pockets")): sourcelist=self.getSourcesListFile() shutil.copy(sourcelist.name, tmpdir+"/etc/apt/sources.list") with open(tmpdir + '/etc/apt/sources.list', 'r') as fp: print(fp.read()) # move the cache debs self._populateWithCachedDebs(tmpdir) print("Updating the chroot") ret = self._runApt(tmpdir,"update") print("apt update returned %s" % ret) if ret != 0: return False # run it three times to work around network issues for i in range(3): ret = self._runApt(tmpdir,"dist-upgrade") print("apt dist-upgrade returned %s" % ret) if ret != 0: return False print("installing basepkg") ret = self._runApt(tmpdir,"install", [self.config.get("NonInteractive","BasePkg")]) print("apt returned %s" % ret) if ret != 0: return False CMAX = 4000 pkgs = self.config.getListFromFile("NonInteractive","AdditionalPkgs") while(len(pkgs)) > 0: print("installing additional: %s" % pkgs[:CMAX]) ret= self._runApt(tmpdir,"install",pkgs[:CMAX]) print("apt(2) returned: %s" % ret) if ret != 0: self._cacheDebs(tmpdir) return False pkgs = pkgs[CMAX+1:] if self.config.has_option("NonInteractive","PostBootstrapScript"): script = self.config.get("NonInteractive","PostBootstrapScript") if os.path.exists(script): shutil.copy(script, os.path.join(tmpdir,"tmp")) self._runInChroot(tmpdir,[os.path.join("/tmp",script)]) else: print("WARNING: %s not found" % script) try: amount = self.config.get("NonInteractive","RandomPkgInstall") self._tryRandomPkgInstall(amount) except configparser.NoOptionError: pass print("Caching debs") self._cacheDebs(tmpdir) print("Cleaning chroot") ret = self._runApt(tmpdir,"clean") if ret != 0: return False print("building tarball: '%s'" % outfile) os.chdir(tmpdir) ret = subprocess.call(["tar","czf",outfile,"."]) print("tar returned %s" % ret) return True def _populateWithCachedDebs(self, tmpdir): # now populate with hardlinks for the debs if self.cachedir: print("Linking cached debs into chroot") for f in glob.glob(self.cachedir+"/*.deb"): try: os.link(f, tmpdir+"/var/cache/apt/archives/%s" % os.path.basename(f)) except OSError as e: print("Can't link: %s (%s)" % (f, e)) return True def upgrade(self, tarball=None): if not tarball: tarball = self.tarball assert(tarball != None) print("running upgrade on: %s" % tarball) tmpdir = self.tmpdir #self._runApt(tmpdir, "install",["apache2"]) self._populateWithCachedDebs(tmpdir) # copy itself to the chroot (resolve symlinks) targettmpdir = os.path.join(tmpdir,"tmp","dist-upgrade") if not os.path.exists(targettmpdir): os.makedirs(targettmpdir) for f in glob.glob("%s/*" % self.upgradefilesdir): if not os.path.isdir(f): shutil.copy(f, targettmpdir) # copy the profile if os.path.exists(self.profile): print("Copying '%s' to '%s' " % (self.profile, targettmpdir)) shutil.copy(self.profile, targettmpdir) # copy the .cfg and .list stuff from there too for f in glob.glob("%s/*.cfg" % (os.path.dirname(self.profile))): shutil.copy(f, targettmpdir) for f in glob.glob("%s/*.list" % (os.path.dirname(self.profile))): shutil.copy(f, targettmpdir) # run it pid = os.fork() if pid == 0: os.chroot(tmpdir) os.chdir("/tmp/dist-upgrade") os.system("mount -t devpts devpts /dev/pts") os.system("mount -t sysfs sysfs /sys") os.system("mount -t proc proc /proc") os.system("mount -t binfmt_misc binfmt_misc /proc/sys/fs/binfmt_misc") if os.path.exists("/tmp/dist-upgrade/dist-upgrade.py"): os.execl("/tmp/dist-upgrade/dist-upgrade.py", "/tmp/dist-upgrade/dist-upgrade.py") else: os.execl("/usr/bin/do-release-upgrade", "/usr/bin/do-release-upgrade","-d", "-f","DistUpgradeViewNonInteractive") else: print("Parent: waiting for %s" % pid) (id, exitstatus) = os.waitpid(pid, 0) print("Child exited (%s, %s): %s" % (id, exitstatus, os.WEXITSTATUS(exitstatus))) # copy the result for f in glob.glob(tmpdir+"/var/log/dist-upgrade/*"): print("copying result to: ", self.resultdir) shutil.copy(f, self.resultdir) # cache debs and cleanup self._cacheDebs(tmpdir) self._umount(tmpdir) shutil.rmtree(tmpdir) return (exitstatus == 0) def _unpackToTmpdir(self, baseTarBall): # unpack the tarball self.tmpdir = tmpdir = self._getTmpDir() os.chdir(tmpdir) ret = subprocess.call(["tar","xzf",baseTarBall]) if ret != 0: return None return tmpdir def _dpkgDivert(self, tmpdir): for d in self.diverts: cmd = ["chroot",tmpdir, "dpkg-divert","--add","--local", "--divert",d+".thereal", "--rename",d] ret = subprocess.call(cmd) if ret != 0: print("dpkg-divert returned: %s" % ret) shutil.copy(tmpdir+"/bin/true",tmpdir+d) def test(self): # FIXME: add some sanity testing here return True if __name__ == "__main__": if len(sys.argv) > 1: profilename = sys.argv[1] else: profilename = "default" chroot = UpgradeTestBackendChroot(profilename) tarball = "%s/tarball/dist-upgrade-%s.tar.gz" % (os.getcwd(),profilename) if not os.path.exists(tarball): print("No existing tarball found, creating a new one") chroot.bootstrap(tarball) chroot.upgrade(tarball) #tmpdir = chroot._unpackToTmpdir(tarball) #chroot._dpkgDivert(tmpdir) #print(tmpdir) auto-upgrade-testing/AutoUpgradeTester/__init__.py0000664000000000000000000000011612076525005017536 0ustar from DistUpgrade import utils from DistUpgrade import DistUpgradeConfigParser auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackendLXC.py0000664000000000000000000002010012076525005022040 0ustar # ec2 backend from __future__ import absolute_import, print_function from AutoUpgradeTester.UpgradeTestBackendSSH import UpgradeTestBackendSSH from DistUpgrade.sourceslist import SourcesList import apt_pkg import atexit import glob import lxc import os import shutil class UpgradeTestBackendLXC(UpgradeTestBackendSSH): """ LXC backend """ def __init__(self, profile): UpgradeTestBackendSSH.__init__(self, profile) self.profiledir = os.path.abspath(os.path.dirname(profile)) self.profilename = "upgrader-%s" % self.config.get("NonInteractive","ProfileName") self.lxc_container = lxc.Container(self.profilename) atexit.register(self._cleanup) def _cleanup(self): print("_cleanup()") if self.lxc_container.running: self.lxc_container.stop() self.lxc_container.destroy() def restart(self): print("_restart()") self.stop() self.start() def start(self): print("_start()") self.lxc_container.start() self.lxc_ips = self.lxc_container.get_ips() self.ssh_hostname = self.lxc_ips[0] self.ssh_port = "22" def stop(self): print("_stop()") self.lxc_container.stop() self.ssh_hostname = None self.ssh_port = None def bootstrap(self, force=False): print("bootstrap()") src_release = self.config.getWithDefault("DEFAULT", "SourceRelease", "precise") src_arch = self.config.getWithDefault("KVM", "Arch", "i386") self.lxc_container.create("ubuntu", {"release": src_release, "arch": src_arch}) os.makedirs("/var/lib/lxc/%s/rootfs/root/.ssh/" % self.profilename) shutil.copy("%s.pub" % self.ssh_key, "/var/lib/lxc/%s/rootfs/root/.ssh/authorized_keys" % self.profilename) # get common vars basepkg = self.config.get("NonInteractive","BasePkg") basepkg += " language-pack-en linux-generic" # start the VM self.start() # FIXME: Prevents lxc-net from starting and cutting network (if eth0 and lxcbr0 end up in the same subnet) lxcnet = open("/var/lib/lxc/%s/rootfs/etc/init/lxc-net.override" % self.profilename, "w+") lxcnet.write("pre-start exec true\npost-stop exec true\n") lxcnet.close() # FIXME: Some workarounds # /usr/sbin/update-grub => fails in LXC # /usr/bin/cgroups-mount => fails in LXC unless using the nesting apparmor profile # /usr/bin/cgroups-umount => fails in LXC unless using the nesting apparmor profile for path in ("/usr/sbin/update-grub", "/usr/bin/cgroups-mount", "/usr/bin/cgroups-umount"): self._runInImage(["dpkg-divert", "--rename", "--divert", "%s.orig" % path, "--package", "auto-upgrade-testing", "--add", path]) self._runInImage(["cp", "/bin/true", path]) # prepare the sources.list (needed because a AMI may have any # sources.list) sources = self.getSourcesListFile() ret = self._copyToImage(sources.name, "/etc/apt/sources.list") assert(ret == 0) # install some useful stuff ret = self._runInImage(["apt-get","update"]) assert(ret == 0) for i in range(3): ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install", "--allow-unauthenticated", "-y", basepkg ]) assert(ret == 0) # Configure X ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install", "--allow-unauthenticated", "-y", "xserver-xorg-video-dummy" ]) assert(ret == 0) with open("/var/lib/lxc/%s/rootfs/usr/share/X11/xorg.conf.d/00-dummy.conf" % self.profilename, "w+") as fd: fd.write(""" Section "Device" Identifier "dummy" Driver "dummy" EndSection """) CMAX = 4000 pkgs = self.config.getListFromFile("NonInteractive","AdditionalPkgs") while(len(pkgs)) > 0: print("installing additonal: %s" % pkgs[:CMAX]) ret= self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install","--reinstall", "--allow-unauthenticated", "-y"]+pkgs[:CMAX]) print("apt(2) returned: %s" % ret) if ret != 0: #self._cacheDebs(tmpdir) print("apt returned a error, stopping") self.stop_instance() return False pkgs = pkgs[CMAX+1:] if self.config.has_option("NonInteractive","PostBootstrapScript"): script = self.config.get("NonInteractive","PostBootstrapScript") print("have PostBootstrapScript: %s" % script) if os.path.exists(script): self._runInImage(["mkdir","/upgrade-tester"]) self._copyToImage(script, "/upgrade-tester") print("running script: %s" % os.path.join("/tmp",script)) self._runInImage([os.path.join("/upgrade-tester",script)]) else: print("WARNING: %s not found" % script) if self.config.getWithDefault("NonInteractive", "UpgradeFromDistOnBootstrap", False): print("running apt-get upgrade in from dist (after bootstrap)") for i in range(3): ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","--allow-unauthenticated", "-y","dist-upgrade"]) assert(ret == 0) print("Cleaning image") ret = self._runInImage(["apt-get","clean"]) assert(ret == 0) # FIXME: probably should be done in one of the generic classes print("configuring upgrader") ret = self._runInImage(["sed", "-i", "s/lts/normal/g", "/etc/update-manager/release-upgrades"]) self.restart() return True def upgrade(self): print("upgrade()") # clean from any leftover pyc files for f in glob.glob("%s/*.pyc" % self.upgradefilesdir): os.unlink(f) print("Starting for upgrade") assert(self.ssh_hostname) # copy the profile if os.path.exists(self.profile): print("Copying '%s' to image overrides" % self.profile) self._runInImage(["mkdir","-p","/etc/update-manager/release-upgrades.d"]) self._copyToImage(self.profile, "/etc/update-manager/release-upgrades.d/") # copy test repo sources.list (if needed) test_repo = self.config.getWithDefault("NonInteractive","AddRepo","") if test_repo: test_repo = os.path.join(os.path.dirname(self.profile), test_repo) self._copyToImage(test_repo, "/etc/apt/sources.list.d") sourcelist = self.getSourcesListFile() apt_pkg.Config.Set("Dir::Etc", os.path.dirname(sourcelist.name)) apt_pkg.Config.Set("Dir::Etc::sourcelist", os.path.basename(sourcelist.name)) sources = SourcesList(matcherPath=".") sources.load(test_repo) # add the uri to the list of valid mirros in the image for entry in sources.list: if (not (entry.invalid or entry.disabled) and entry.type == "deb"): print("adding %s to mirrors" % entry.uri) self._runInImage(["echo '%s' >> /upgrade-tester/mirrors.cfg" % entry.uri]) # check if we have a bzr checkout dir to run against or # if we should just run the normal upgrader if (os.path.exists(self.upgradefilesdir) and self.config.getWithDefault("NonInteractive", "UseUpgraderFromBzr", True)): self._copyUpgraderFilesFromBzrCheckout() ret = self._runBzrCheckoutUpgrade() else: ret = self._runInImage(["do-release-upgrade","-d", "-f","DistUpgradeViewNonInteractive"]) print("dist-upgrade.py returned: %i" % ret) # copy the result print("coyping the result") self._copyFromImage("/var/log/dist-upgrade/*",self.resultdir) # stop the machine print("Shuting down the container") self.stop() return True auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackend.py0000664000000000000000000001446112076525005021506 0ustar # TargetNonInteractive.py # # abstraction for non-interactive backends (like chroot, qemu) # # Precise/Quantal+ compatibility try: from AutoUpgradeTester.DistUpgradeConfigParser import DistUpgradeConfig except ImportError: from DistUpgrade.DistUpgradeConfigParser import DistUpgradeConfig try: import configparser configparser # pyflakes except ImportError: import ConfigParser as configparser import os import tempfile from shutil import rmtree # refactor the code so that we have # UpgradeTest - the controler object # UpgradeTestImage - abstraction for chroot/qemu/xen class UpgradeTestImage(object): def runInTarget(self, command): pass def copyToImage(self, fromFile, toFile): pass def copyFromImage(self, fromFile, toFile): pass def bootstrap(self, force=False): pass def start(self): pass def stop(self): pass class UpgradeTestBackend(object): """ This is a abstrace interface that all backends (chroot, qemu) should implement - very basic currently :) """ apt_options = ["-y","--allow-unauthenticated"] def __init__(self, profiledir, resultdir=""): " init the backend with the given profile " # init the dirs assert(profiledir != None) profiledir = os.path.normpath(profiledir) profile = os.path.join(os.path.abspath(profiledir), "DistUpgrade.cfg") self.upgradefilesdir = "./DistUpgrade" if os.path.exists("share/post_upgrade_tests/"): self.post_upgrade_tests_dir = "share/post_upgrade_tests/" else: self.post_upgrade_tests_dir = "/usr/share/auto-upgrade-tester/post_upgrade_tests/" # init the rest if os.path.exists(profile): override_cfg_d = os.path.join(profiledir, "..", "override.cfg.d") defaults_cfg_d = os.path.join(profiledir, "..", "defaults.cfg.d") self.profile = os.path.abspath(profile) self.config = DistUpgradeConfig(datadir=os.path.dirname(profile), name=os.path.basename(profile), override_dir=override_cfg_d, defaults_dir=defaults_cfg_d) else: raise IOError("Can't find profile '%s' (%s) " % (profile, os.getcwd())) if resultdir: base_resultdir = resultdir else: base_resultdir = self.config.getWithDefault( "NonInteractive", "ResultDir", "results-upgrade-tester") self.resultdir = os.path.abspath( os.path.join(base_resultdir, profiledir.split("/")[-1])) # Cleanup result directory before new run if os.path.exists(self.resultdir): rmtree(self.resultdir) os.makedirs(self.resultdir) self.fromDist = self.config.get("Sources","From") if "http_proxy" in os.environ and not self.config.has_option("NonInteractive","Proxy"): self.config.set("NonInteractive","Proxy", os.environ["http_proxy"]) elif self.config.has_option("NonInteractive","Proxy"): proxy=self.config.get("NonInteractive","Proxy") os.putenv("http_proxy",proxy) os.putenv("DEBIAN_FRONTEND","noninteractive") self.cachedir = None try: self.cachedir = self.config.get("NonInteractive","CacheDebs") except configparser.NoOptionError: pass # init a sensible environment (to ensure proper operation if # run from cron) os.environ["PATH"] = "/usr/sbin:/usr/bin:/sbin:/bin" def installPackages(self, pkgs): """ install packages in the image """ pass def getSourcesListFile(self): """ creates a temporary sources.list file and returns it to the caller """ # write new sources.list sourceslist = tempfile.NamedTemporaryFile(mode="w+") comps = self.config.getlist("NonInteractive","Components") pockets = self.config.getlist("NonInteractive","Pockets") mirror = self.config.get("NonInteractive","Mirror") sourceslist.write("deb %s %s %s\n" % (mirror, self.fromDist, " ".join(comps))) for pocket in pockets: sourceslist.write("deb %s %s-%s %s\n" % (mirror, self.fromDist,pocket, " ".join(comps))) sourceslist.flush() return sourceslist def bootstrap(self): " bootstaps a pristine install" pass def upgrade(self): " upgrade a given install " pass def test(self): " test if the upgrade was successful " pass def resultsToJunitXML(self, results, outputfile = None): """ Filter results to get Junit XML output :param results: list of results. Each result is a dictionary of the form name: name of the test result: (pass, fail, error) time: execution time of the test in seconds message: optional message in case of failure or error :param output: Output XML to this file instead of returning the value """ from xml.sax.saxutils import escape output = "" testsuite_name = '' res = [x['result'] for x in results] fail_count = res.count('fail') error_count = res.count('error') total_count = len(res) total_time = sum([x['time'] for x in results]) output = """\n""" % ( error_count, fail_count, testsuite_name, total_count,total_time) for result in results: output += """\n""" % ( self.profilename + '.PostUpgradeTest', result['name'][:-3], result['time']) if 'fail' in result['result']: output += """%s\n\n""" % ( 'exception', escape(result['message'])) elif 'error' in result['result']: output += """%s\n\n""" % ( 'exception', escape(result['message'])) output += "\n" output += "\n" if outputfile: with open(outputfile, 'w') as f: f.write(output) else: return output auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackendEC2.py0000664000000000000000000003033312076525005021774 0ustar # ec2 backend from __future__ import absolute_import, print_function from AutoUpgradeTester.UpgradeTestBackendSSH import UpgradeTestBackendSSH from AutoUpgradeTester.UpgradeTestBackend import UpgradeTestBackend from DistUpgrade.sourceslist import SourcesList from boto.ec2.connection import EC2Connection try: import configparser configparser # pyflakes except ImportError: import ConfigParser as configparser import os import sys import glob import time import atexit import apt_pkg # images created with EC2 class NoCredentialsFoundException(Exception): pass class OptionError(Exception): pass # Step to perform for a ec2 upgrade test # # 1. conn = EC2Connect() # 2. reservation = conn.run_instances(image_id = image, security_groups = groups, key_name = key) # 3. wait for instance.state == 'running': # instance.update() # 4. ssh -i root@instance.dns_name # TODO # # Using ebs (elastic block storage) and snapshots for the test # 1. ec2-create-volume -s 80 -z us-east-1a # (check with ec2-describe-instance that its actually in # the right zone) # 2. ec2-attach-volume vol-7bd23de2 -i i-3325ad4 -d /dev/sdh # (do not name it anything but sd*) # 3. mount/use the thing inside the instance # # # Other useful things: # - sda1: root fs # - sda2: free space (~140G) # - sda3: swapspace (~1G) class UpgradeTestBackendEC2(UpgradeTestBackendSSH): " EC2 backend " def __init__(self, profile): UpgradeTestBackend.__init__(self, profile) self.profiledir = os.path.abspath(os.path.dirname(profile)) # ami base name (e.g .ami-44bb5c2d) self.ec2ami = self.config.get("EC2","AMI") self.ssh_key = self.config.get("EC2","SSHKey") try: self.access_key_id = (os.getenv("AWS_ACCESS_KEY_ID") or self.config.get("EC2","access_key_id")) self.secret_access_key = (os.getenv("AWS_SECRET_ACCESS_KEY") or self.config.get("EC2","secret_access_key")) except configparser.NoOptionError: print("Either export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY or") print("set access_key_id and secret_access_key in the profile config") print("file.") sys.exit(1) self._conn = EC2Connection(self.access_key_id, self.secret_access_key) self.ubuntu_official_ami = False if self.config.has_option("EC2","UbuntuOfficialAMI"): self.ubuntu_official_ami = self.config.getboolean("EC2","UbuntuOfficialAMI") try: self.security_groups = self.config.getlist("EC2","SecurityGroups") except configparser.NoOptionError: self.security_groups = [] if self.ssh_key.startswith("./"): self.ssh_key = self.profiledir + self.ssh_key[1:] self.ssh_port = "22" self.instance = None # the public name of the instance, e.g. # ec2-174-129-152-83.compute-1.amazonaws.com self.ssh_hostname = "" # the instance name (e.g. i-3325ad4) self.ec2instance = "" if (self.config.has_option("NonInteractive","RealReboot") and self.config.getboolean("NonInteractive","RealReboot")): raise OptionError("NonInteractive/RealReboot option must be set to False for the ec2 upgrader") atexit.register(self._cleanup) def _cleanup(self): print("_cleanup(): stopping running instance") if self.instance: self.instance.stop() def _enableRootLogin(self): command = ["sudo", "sed", "-i", "-e", "'s,\(.*\)\(ssh-rsa.*\),\\2,'", "/root/.ssh/authorized_keys"] ret = self._runInImageAsUser("ubuntu", command) return (ret == 0) def bootstrap(self, force=False): print("bootstrap()") print("Building new image based on '%s'" % self.ec2ami) # get common vars basepkg = self.config.get("NonInteractive","BasePkg") # start the VM self.start_instance() # prepare the sources.list (needed because a AMI may have any # sources.list) sources = self.getSourcesListFile() ret = self._copyToImage(sources.name, "/etc/apt/sources.list") assert(ret == 0) # install some useful stuff ret = self._runInImage(["apt-get","update"]) assert(ret == 0) # FIXME: instead of this retrying (for network errors with # proxies) we should have a self._runAptInImage() for i in range(3): ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install", "--allow-unauthenticated", "-y",basepkg]) assert(ret == 0) CMAX = 4000 pkgs = self.config.getListFromFile("NonInteractive","AdditionalPkgs") while(len(pkgs)) > 0: print("installing additional: %s" % pkgs[:CMAX]) ret= self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install","--reinstall", "--allow-unauthenticated", "-y"]+pkgs[:CMAX]) print("apt(2) returned: %s" % ret) if ret != 0: #self._cacheDebs(tmpdir) print("apt returned an error, stopping") self.stop_instance() return False pkgs = pkgs[CMAX+1:] if self.config.has_option("NonInteractive","PostBootstrapScript"): script = self.config.get("NonInteractive","PostBootstrapScript") print("have PostBootstrapScript: %s" % script) if os.path.exists(script): self._runInImage(["mkdir","/upgrade-tester"]) self._copyToImage(script, "/upgrade-tester") print("running script: %s" % os.path.join("/tmp", script)) self._runInImage([os.path.join("/upgrade-tester",script)]) else: print("WARNING: %s not found" % script) if self.config.getWithDefault("NonInteractive", "UpgradeFromDistOnBootstrap", False): print("running apt-get upgrade in from dist (after bootstrap)") for i in range(3): ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","--allow-unauthenticated", "-y","dist-upgrade"]) assert(ret == 0) print("Cleaning image") ret = self._runInImage(["apt-get","clean"]) assert(ret == 0) # done with the bootstrap # FIXME: idealy we would reboot here, but its less important # because we can't get a new kernel anyway in ec2 (yet) # - the reboot thing is *not* yet reliable! #self.reboot_instance() # FIXME: support for caching/snapshoting the base image here return True def start_instance(self): print("Starting ec2 instance and wait until it's available") # start the instance reservation = self._conn.run_instances(image_id=self.ec2ami, security_groups=self.security_groups, key_name=self.ssh_key[:-4].split("/")[-1]) self.instance = reservation.instances[0] while self.instance.state == "pending": print("Waiting for instance %s to come up..." % self.instance.id) time.sleep(10) self.instance.update() print("It's up: hostname =", self.instance.dns_name) self.ssh_hostname = self.instance.dns_name self.ec2instance = self.instance.id # now sping until ssh comes up in the instance if self.ubuntu_official_ami: user = "ubuntu" else: user = "root" for i in range(900): time.sleep(1) if self.ping(user): print("instance available via ssh ping") break else: print("Could not connect to instance after 900s, exiting") return False # re-enable root login if needed if self.ubuntu_official_ami: print("Re-enabling root login... ",) ret = self._enableRootLogin() if ret: print("Done!") else: print("Oops, failed to enable root login...") assert (ret == True) # the official image seems to run a update on startup?!? print("waiting for the official image to leave apt alone") time.sleep(10) return True def reboot_instance(self): " reboot a ec2 instance and wait until its available again " self.instance.reboot() # FIMXE: find a better way to know when the instance is # down - maybe with "-v" ? time.sleep(5) while True: if self._runInImage(["/bin/true"]) == 0: print("instance rebooted") break def stop_instance(self): " permanently stop a instance (it can never be started again " # terminates are final - all data is lost self.instance.stop() # wait until its down while True: if self._runInImage(["/bin/true"]) != 0: print("instance stopped") break def upgrade(self): print("upgrade()") # clean from any leftover pyc files for f in glob.glob("%s/*.pyc" % self.upgradefilesdir): os.unlink(f) print("Starting for upgrade") assert(self.ec2instance) assert(self.ssh_hostname) # copy the profile if os.path.exists(self.profile): print("Copying '%s' to image overrides" % self.profile) self._runInImage(["mkdir","-p","/etc/update-manager/release-upgrades.d"]) self._copyToImage(self.profile, "/etc/update-manager/release-upgrades.d/") # copy test repo sources.list (if needed) test_repo = self.config.getWithDefault("NonInteractive","AddRepo","") if test_repo: test_repo = os.path.join(os.path.dirname(self.profile), test_repo) self._copyToImage(test_repo, "/etc/apt/sources.list.d") sourcelist = self.getSourcesListFile() apt_pkg.config.set("Dir::Etc", os.path.dirname(sourcelist.name)) apt_pkg.config.set("Dir::Etc::sourcelist", os.path.basename(sourcelist.name)) sources = SourcesList(matcherPath=".") sources.load(test_repo) # add the uri to the list of valid mirros in the image for entry in sources.list: if (not (entry.invalid or entry.disabled) and entry.type == "deb"): print("adding %s to mirrors" % entry.uri) self._runInImage(["echo '%s' >> /upgrade-tester/mirrors.cfg" % entry.uri]) # check if we have a bzr checkout dir to run against or # if we should just run the normal upgrader if (os.path.exists(self.upgradefilesdir) and self.config.getWithDefault("NonInteractive", "UseUpgraderFromBzr", True)): self._copyUpgraderFilesFromBzrCheckout() ret = self._runBzrCheckoutUpgrade() else: ret = self._runInImage(["do-release-upgrade","-d", "-f","DistUpgradeViewNonInteractive"]) print("dist-upgrade.py returned: %i" % ret) # copy the result print("copying the result") self._copyFromImage("/var/log/dist-upgrade/*",self.resultdir) # stop the machine print("Shutting down the VM") self.stop_instance() return True def test(self): # FIXME: add some tests here to see if the upgrade worked # this should include: # - new kernel is runing (run uname -r in target) # - did it sucessfully rebooted # - is X runing # - generate diff of upgrade vs fresh install # ... return True # compatibility for the auto-install-tester def start(self): self.start_instance() def stop(self): self.stop_instance() def saveVMSnapshot(self): print("saveVMSnapshot not supported yet") def restoreVMSnapshot(self): print("restoreVMSnapshot not supported yet") # vim:ts=4:sw=4:et auto-upgrade-testing/AutoUpgradeTester/UpgradeTestBackendQemu.py0000664000000000000000000006307212076525005022340 0ustar # qemu backend from __future__ import absolute_import, print_function from AutoUpgradeTester.UpgradeTestBackendSSH import UpgradeTestBackendSSH from DistUpgrade.sourceslist import SourcesList try: import configparser configparser # pyflakes except ImportError: import ConfigParser as configparser import subprocess import os import sys import shutil import glob import time import tempfile import atexit import apt_pkg import fcntl # Precise/Quantal compatibility try: from AutoUpgradeTester.utils import is_port_already_listening except ImportError: from DistUpgrade.utils import is_port_already_listening # images created with http://bazaar.launchpad.net/~mvo/ubuntu-jeos/mvo # ./ubuntu-jeos-builder --vm kvm --kernel-flavor generic --suite feisty --ssh-key `pwd`/ssh-key.pub --components main,restricted --rootsize 20G # # TODO: # - add support to boot certain images with certain parameters # (dapper-386 needs qemu/kvm with "-no-acpi" to boot reliable) # - add option to use pre-done base images # the bootstrap() step is then a matter of installing the right # packages into the image (via _runInImage()) # # - refactor and move common code to UpgradeTestBackend # - convert ChrootNonInteractive # - benchmark qemu/qemu+kqemu/kvm/chroot # - write tests (unittest, doctest?) # - offer "test-upgrade" feature on real system, run it # as "qemu -hda /dev/hda -snapshot foo -append init=/upgrade-test" # (this *should* write the stuff to the snapshot file # - add "runInTarget()" that will write a marker file so that we can # re-run a command if it fails the first time (or fails because # a fsck was done and reboot needed in the VM etc) # - start a X session with the gui-upgrader in a special # "non-interactive" mode to see if the gui upgrade would work too class NoImageFoundException(Exception): pass class PortInUseException(Exception): pass class NoPortsException(Exception): pass class UpgradeTestBackendQemu(UpgradeTestBackendSSH): " qemu/kvm backend - need qemu >= 0.9.0" QEMU_DEFAULT_OPTIONS = [ "-monitor","stdio", "-localtime", "-no-reboot", # exit on reboot # "-no-kvm", # crashes sometimes with kvm HW ] def __init__(self, profile): UpgradeTestBackendSSH.__init__(self, profile) self.qemu_options = self.QEMU_DEFAULT_OPTIONS[:] self.qemu_pid = None self.profiledir = profile self.profile_override = os.path.join( self.profiledir, "..", "override.cfg.d") # get the kvm binary self.qemu_binary = self.config.getWithDefault("KVM","KVM","kvm") # setup mount dir/imagefile location self.baseimage = self.config.get("KVM", "BaseImage") if not os.path.exists(self.baseimage): print("Missing '%s' base image, need to build it now" % self.baseimage) arch = self.config.getWithDefault("KVM", "Arch", "i386") rootsize = self.config.getWithDefault("KVM", "RootSize", "80000") destdir = "ubuntu-kvm-%s-%s" % (arch, self.fromDist) ret = subprocess.call(["sudo", "ubuntu-vm-builder","kvm", self.fromDist, "--kernel-flavour", "generic", "--ssh-key", "%s.pub" % self.ssh_key , "--components", "main,restricted", "--rootsize", rootsize, "--addpkg", "openssh-server", "--destdir", destdir, "--arch", arch]) # move the disk in place, ubuntu-vm-builder uses a random filename shutil.move(glob.glob("%s/*.qcow2" % destdir)[0], self.baseimage) # remove old tree to ensure that subsequent runs work shutil.rmtree(destdir) if ret != 0: raise NoImageFoundException # check if we want virtio here and default to yes try: self.virtio = self.config.getboolean("KVM","Virtio") except configparser.NoOptionError: self.virtio = True if self.virtio: self.qemu_options.extend(["-net","nic,model=virtio"]) self.qemu_options.extend(["-net","user"]) # swapimage if self.config.getWithDefault("KVM","SwapImage",""): self.qemu_options.append("-hdb") self.qemu_options.append(self.config.get("KVM","SwapImage")) # regular image self.profilename = self.config.get("NonInteractive","ProfileName") imagedir = self.config.get("KVM","ImageDir") self.image = os.path.join(imagedir, "test-image.%s" % self.profilename) # make ssh login possible (localhost 54321) available ssh_port = int(self.config.getWithDefault("KVM","SshPort","54321")) (self.ssh_lock, ssh_port) = self.getFreePort(port_base=ssh_port) if not self.ssh_lock: raise NoPortsException("Couldn't allocate SSH port.") self.ssh_port = str(ssh_port) print("using ssh port: %s" % self.ssh_port) self.ssh_hostname = "localhost" self.qemu_options.append("-redir") self.qemu_options.append("tcp:%s::22" % self.ssh_port) # vnc port/display VNC_BASE_PORT = 5900 vncport = int(self.config.getWithDefault("KVM","VncNum", "0")) + VNC_BASE_PORT (self.vnc_lock, vncport) = self.getFreePort(port_base=vncport) if not self.vnc_lock: raise NoPortsException("Couldn't allocate VNC port.") print("using VncNum: %s" % vncport) self.qemu_options.append("-vnc") self.qemu_options.append("localhost:%s" % str(vncport - VNC_BASE_PORT)) # make the memory configurable mem = self.config.getWithDefault("KVM","VirtualRam","1536") self.qemu_options.append("-m") self.qemu_options.append(str(mem)) # check if the ssh port is in use if subprocess.call("netstat -t -l -n |grep 0.0.0.0:%s" % self.ssh_port, shell=True) == 0: raise PortInUseException("the port is already in use (another upgrade tester is running?)") # register exit handler to ensure that we quit kvm on exit atexit.register(self.stop) def __del__(self): """ Destructor Clean-up lockfiles """ for lock in (self.ssh_lock, self.vnc_lock): lockpath = lock.name print("Releasing lock: %s" % lockpath) lock.close() os.unlink(lockpath) def genDiff(self): """ generate a diff that compares a fresh install to a upgrade. ideally that should be empty Ensure that we always run this *after* the regular upgrade was run (otherwise it is useless) """ # generate ls -R output of test-image ( self.start() self._runInImage(["find", "/bin", "/boot", "/etc/", "/home", "/initrd", "/lib", "/root", "/sbin/", "/srv", "/usr", "/var"], stdout=open(self.resultdir+"/upgrade_install.files","w")) self._runInImage(["dpkg","--get-selections"], stdout=open(self.resultdir+"/upgrade_install.pkgs","w")) self._runInImage(["tar","cvf","/tmp/etc-upgrade.tar","/etc"]) self._copyFromImage("/tmp/etc-upgrade.tar", self.resultdir) self.stop() # HACK: now build fresh toDist image - it would be best if self.fromDist = self.config.get("Sources","To") self.config.set("Sources","From", self.config.get("Sources","To")) diff_image = os.path.join(self.profiledir, "test-image.diff") # FIXME: we need to regenerate the base image too, but there is no # way to do this currently without running as root # as a workaround we regenerate manually every now and then # and use UpgradeFromDistOnBootstrap=true here self.config.set("KVM","CacheBaseImage", "false") self.config.set("NonInteractive","UpgradeFromDistOnBootstrap","true") self.baseimage = "jeos/%s-i386.qcow2" % self.config.get("Sources","To") self.image = diff_image print("bootstrapping into %s" % diff_image) self.bootstrap() print("bootstrap finished") self.start() print("generating file diff list") self._runInImage(["find", "/bin", "/boot", "/etc/", "/home", "/initrd", "/lib", "/root", "/sbin/", "/srv", "/usr", "/var"], stdout=open(self.resultdir+"/fresh_install","w")) self._runInImage(["dpkg","--get-selections"], stdout=open(self.resultdir+"/fresh_install.pkgs","w")) self._runInImage(["tar","cvf","/tmp/etc-fresh.tar","/etc"]) self._copyFromImage("/tmp/etc-fresh.tar", self.resultdir) self.stop() # now compare the diffs pass def bootstrap(self, force=False): print("bootstrap()") # move old crash files away so that test() is not # confused by them for f in glob.glob(self.resultdir+"/*.crash"): shutil.move(f, f+".old") # copy image into place, use baseimage as template # we expect to be able to ssh into the baseimage to # set it up if (not force and os.path.exists("%s.%s" % (self.image,self.fromDist)) and self.config.has_option("KVM","CacheBaseImage") and self.config.getboolean("KVM","CacheBaseImage")): print("Not bootstrapping again, we have a cached BaseImage") shutil.copy("%s.%s" % (self.image,self.fromDist), self.image) return True print("Building new image '%s' based on '%s'" % (self.image, self.baseimage)) shutil.copy(self.baseimage, self.image) # get common vars basepkg = self.config.get("NonInteractive","BasePkg") additional_base_pkgs = self.config.getlist("Distro","BaseMetaPkgs") # start the VM self.start() # FIXME: make this part of the apt env # otherwise we get funny debconf promtps for # e.g. the xserver #export DEBIAN_FRONTEND=noninteractive #export APT_LISTCHANGES_FRONTEND=none # # generate static network config (NetworkManager likes # to reset the dhcp interface and that sucks when # going into the VM with ssh) nm = self.config.getWithDefault("NonInteractive","WorkaroundNetworkManager","") if nm: interfaces = tempfile.NamedTemporaryFile(mode="w+") interfaces.write(""" auto lo iface lo inet loopback auto eth0 iface eth0 inet static address 10.0.2.15 netmask 255.0.0.0 gateway 10.0.2.2 """) interfaces.flush() self._copyToImage(interfaces.name, "/etc/network/interfaces") # generate hosts file, the default hosts file contains # "127.0.0.1 ubuntu. ubuntu" for some reason and the missing # domain part after the "." makes e.g. postfix rather unhappy etc_hosts = tempfile.NamedTemporaryFile(mode="w+") etc_hosts.write('127.0.0.1 localhost\n') etc_hosts.write('127.0.0.1 upgrade-test-vm\n') etc_hosts.flush() self._copyToImage(etc_hosts.name, "/etc/hosts") # make dpkg fast^Wunsafe^WFAST # Disabled / Breaks lucid #self._force_dpkg_unsafe_io() # generate apt.conf proxy = self.config.getWithDefault("NonInteractive","Proxy","") if proxy: aptconf = tempfile.NamedTemporaryFile(mode="w+") aptconf.write('Acquire::http::proxy "%s";' % proxy) aptconf.flush() self._copyToImage(aptconf.name, "/etc/apt/apt.conf") # tzdata is unhappy without that file tzone = tempfile.NamedTemporaryFile(mode="w+") tzone.write("Europe/Berlin") tzone.flush() self._copyToImage(tzone.name, "/etc/timezone") aptclone = self.config.getWithDefault('NonInteractive', 'AptCloneFile', '') if not aptclone: # create /etc/apt/sources.list sources = self.getSourcesListFile() self._copyToImage(sources.name, "/etc/apt/sources.list") # install some useful stuff ret = self._runInImage(["apt-get","update"]) assert ret == 0 # FIXME: instead of this retrying (for network errors with # proxies) we should have a self._runAptInImage() for i in range(3): ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install", "-y",basepkg]+additional_base_pkgs) assert ret == 0 else: dst_clonename = '/tmp/apt-clone.tgz' self._copyToImage(aptclone, dst_clonename) ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive", "apt-get", "install", "-y", "apt-clone"]) assert ret == 0 print("Restoring clone from %s" % aptclone) ret = self._runInImage(['DEBIAN_FRONTEND=noninteractive', 'apt-clone', 'restore', dst_clonename]) # FIXME: what action should be taken when a package failed # to restore? if ret != 0: print("WARNING: Some packages failed to restore. Continuing anyway!") #assert ret == 0 CMAX = 4000 pkgs = self.config.getListFromFile("NonInteractive","AdditionalPkgs") while(len(pkgs)) > 0: print("installing additional: %s" % pkgs[:CMAX]) ret= self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","install","--reinstall","-y"]+pkgs[:CMAX]) print("apt(2) returned: %s" % ret) if ret != 0: #self._cacheDebs(tmpdir) self.stop() return False pkgs = pkgs[CMAX+1:] # Copy additional data to the image that can the be used by the # post bootstrap script # Data is copied to /upgrade-tester/data # Value is a list of files separated by commas datadir = '/upgrade-tester/data' self._runInImage(["mkdir", "-p", datadir]) if self.config.has_option("NonInteractive", "PostBootstrapData"): data = self.config.get("NonInteractive", "PostBootstrapData") for datafile in data.split(','): self._copyToImage(datafile, datadir) if self.config.has_option("NonInteractive","PostBootstrapScript"): script = self.config.get("NonInteractive","PostBootstrapScript") print("have PostBootstrapScript: %s" % script) if os.path.exists(script): self._copyToImage(script, "/upgrade-tester") self._copyToImage(glob.glob(os.path.dirname( self.profile)+"/*.cfg"), "/upgrade-tester") script_name = os.path.basename(script) self._runInImage(["chmod","755", os.path.join("/upgrade-tester",script_name)]) print("running script: %s" % script_name) cmd = os.path.join("/upgrade-tester",script_name) ret = self._runInImage(["cd /upgrade-tester; %s" % cmd]) print("PostBootstrapScript returned: %s" % ret) assert ret == 0, "PostBootstrapScript returned non-zero" else: print("WARNING: %s not found" % script) if self.config.getWithDefault("NonInteractive", "UpgradeFromDistOnBootstrap", False): print("running apt-get upgrade in from dist (after bootstrap)") for i in range(3): ret = self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","-y","dist-upgrade"]) assert ret == 0, "dist-upgrade returned %s" % ret print("Cleaning image") ret = self._runInImage(["apt-get","clean"]) assert ret == 0, "apt-get clean returned %s" % ret # FIXME: probably should be done in one of the generic classes print("configuring upgrader") ret = self._runInImage(["sed", "-i", "s/lts/normal/g", "/etc/update-manager/release-upgrades"]) # done with the bootstrap self.stop() # copy cache into place (if needed) if (self.config.has_option("KVM","CacheBaseImage") and self.config.getboolean("KVM","CacheBaseImage")): shutil.copy(self.image, "%s.%s" % (self.image,self.fromDist)) return True def saveVMSnapshot(self,name): # savevm print("savevm") self.stop() shutil.copy(self.image, self.image+"."+name) return # *sigh* buggy :/ #self.qemu_pid.stdin.write("stop\n") #self.qemu_pid.stdin.write("savevm %s\n" % name) #self.qemu_pid.stdin.write("cont\n") def delVMSnapshot(self,name): print("delvm") self.qemu_pid.stdin.write("delvm %s\n" % name) def restoreVMSnapshot(self,name): print("restorevm") self.stop() shutil.copy(self.image+"."+name, self.image) return # loadvm # *sigh* buggy :/ #self.qemu_pid.stdin.write("stop\n") #self.qemu_pid.stdin.write("loadvm %s\n" % name) #self.qemu_pid.stdin.write("cont\n") def start(self): if self.qemu_pid != None: print("already running") return True # mvo: disabled for now, hardy->lucid does not work well with it # (random hangs) #if self.virtio: # drive = ["-drive", "file=%s,if=virtio,boot=on" % self.image] #else: drive = ["-hda", self.image] # build cmd cmd = [self.qemu_binary]+drive+self.qemu_options print("Starting %s" % cmd) self.qemu_pid = subprocess.Popen(cmd, stdin=subprocess.PIPE) # spin here until ssh has come up and we can login now = time.time() while True: if self.qemu_pid.poll(): res = self.qemu_pid.wait() print("qemu stopped unexpectedly with exit code '%s'" % res) return False time.sleep(1) if self._runInImage(["/bin/true"]) == 0: break if (time.time() - now) > 900: print("Could not start image after 900s, exiting") return False return True def stop(self): " we stop because we run with -no-reboot" print("stop") if self.qemu_pid: print("stop pid: ", self.qemu_pid) self._runInImage(["/sbin/reboot"]) print("waiting for qemu to shutdown") for i in range(600): if self.qemu_pid.poll() is not None: print("poll() returned") break time.sleep(1) else: print("Not stopped after 600s, killing ") try: os.kill(int(self.qemu_pid.pid), 15) time.sleep(10) os.kill(int(self.qemu_pid.pid), 9) except Exception as e: print("FAILED to kill %s '%s'" % (self.qemu_pid, e)) self.qemu_pid = None print("qemu stopped") def _force_dpkg_unsafe_io(self): print("Adding dpkg force-unsafe-io") dpkg_unsafe_io = tempfile.NamedTemporaryFile(mode="w+") dpkg_unsafe_io.write('force-unsafe-io\n') dpkg_unsafe_io.flush() self._copyToImage( dpkg_unsafe_io.name, "/etc/dpkg/dpkg.cfg.d/auto-upgrade-tester") def upgrade(self): print("upgrade()") # clean from any leftover pyc files for f in glob.glob("%s/*.pyc" % self.upgradefilesdir): os.unlink(f) print("Starting for upgrade") if not self.start(): return False # make dpkg fast^Wunsafe^WFAST # Disabled / Breaks lucid #self._force_dpkg_unsafe_io() # copy the profile if os.path.exists(self.profile): print("Copying '%s' to image overrides" % self.profile) self._runInImage(["mkdir","-p","/etc/update-manager/release-upgrades.d"]) self._copyToImage(self.profile, "/etc/update-manager/release-upgrades.d/") for override_cfg in glob.glob( os.path.abspath(os.path.join(self.profile_override, "*.cfg"))): print("Copying '%s' to image overrides" % override_cfg) self._copyToImage( override_cfg, "/etc/update-manager/release-upgrades.d/") # copy test repo sources.list (if needed) test_repo = self.config.getWithDefault("NonInteractive","AddRepo","") if test_repo: test_repo = os.path.join(os.path.dirname(self.profile), test_repo) self._copyToImage(test_repo, "/etc/apt/sources.list.d") sourcelist = self.getSourcesListFile() apt_pkg.config.set("Dir::Etc", os.path.dirname(sourcelist.name)) apt_pkg.config.set("Dir::Etc::sourcelist", os.path.basename(sourcelist.name)) sources = SourcesList(matcherPath=".") sources.load(test_repo) # add the uri to the list of valid mirros in the image self._runInImage(["mkdir","-p","/upgrade-tester"]) self._runInImage(["echo -e '[Sources]\nValidMirrors=/upgrade-tester/new_mirrors.cfg' > /etc/update-manager/release-upgrades.d/new_mirrors.cfg"]) for entry in sources.list: if (not (entry.invalid or entry.disabled) and entry.type == "deb"): print("adding %s to mirrors" % entry.uri) self._runInImage(["echo '%s' >> /upgrade-tester/new_mirrors.cfg" % entry.uri]) # upgrade *before* the regular upgrade runs if self.config.getWithDefault("NonInteractive", "AddRepoUpgradeImmediately", False): self._runInImage(["apt-get", "update"]) self._runInImage(["DEBIAN_FRONTEND=noninteractive","apt-get","-y","dist-upgrade", "--allow-unauthenticated"]) apt_conf = self.config.getWithDefault("NonInteractive","AddAptConf","") if apt_conf: apt_conf = os.path.join(os.path.dirname(self.profile), apt_conf) self._copyToImage(apt_conf, "/etc/apt/apt.conf.d") # check if we have a bzr checkout dir to run against or # if we should just run the normal upgrader cmd_prefix=[] debconf_log = self.config.getWithDefault( 'NonInteractive', 'DebconfLog', '') if debconf_log: cmd_prefix=['export DEBIAN_FRONTEND=editor EDITOR="cat>>%s";' % debconf_log] print("Logging debconf prompts to %s" % debconf_log) if not self.config.getWithDefault("NonInteractive","ForceOverwrite", False): print("Disabling ForceOverwrite") cmd_prefix += ["export RELEASE_UPGRADE_NO_FORCE_OVERWRITE=1;"] if (os.path.exists(self.upgradefilesdir) and self.config.getWithDefault("NonInteractive", "UseUpgraderFromBzr", True)): print("Using ./DistUpgrade/* for the upgrade") self._copyUpgraderFilesFromBzrCheckout() ret = self._runBzrCheckoutUpgrade(cmd_prefix) else: print("Using do-release-upgrade for the upgrade") ret = self._runInImage(cmd_prefix+["do-release-upgrade","-d", "-f","DistUpgradeViewNonInteractive"]) print("dist-upgrade.py returned: %i" % ret) # copy the result print("coyping the result") self._copyFromImage("/var/log/dist-upgrade/*",self.resultdir) self._copyFromImage("/var/log/dpkg.log",self.resultdir) # give the ssh output extra time time.sleep(10) # stop the machine print("Shuting down the VM") self.stop() return (ret == 0) def getFreePort(self, port_base=1025, prefix='auto-upgrade-tester'): """ Find a free port and lock it when found :param port_base: Base port number. :param prefix: Prefix name for the lock :return: (lockfile, portnumber) """ # allows the system to be configurable lockdir = "/var/lock" for port_inc in range(0, 100): port_num = port_base + port_inc if is_port_already_listening(port_num): print("Port %d already in use. Skipping!" % port_num) continue lockfilepath = os.path.join(lockdir, '%s.%d.lock' % (prefix, port_num)) # FIXME: we can use apt_pkg.get_lock() here instead if not os.path.exists(lockfilepath): open(lockfilepath, 'w').close() lock = open(lockfilepath, 'r+') try: fcntl.flock(lock, fcntl.LOCK_EX|fcntl.LOCK_NB) return (lock, port_num) except IOError: print("Port %d already locked. Skipping!" % port_num) lock.close() print("No free port found. Aborting!") return (None, None) if __name__ == "__main__": # FIXME: very rough proof of conecpt, unify with the chroot # and automatic-upgrade code # see also /usr/sbin/qemu-make-debian-root qemu = UpgradeTestBackendQemu(sys.argv[1],".") #qemu.bootstrap() #qemu.start() #qemu._runInImage(["ls","/"]) #qemu.stop() qemu.upgrade() # FIXME: now write something into rc.local again and run reboot # and see if we come up with the new kernel auto-upgrade-testing/tests/0000775000000000000000000000000012076525005013162 5ustar auto-upgrade-testing/tests/test_pyflakes.py0000775000000000000000000000122312076525005016412 0ustar import os import subprocess import unittest PYFLAKES_BLACKLIST=[ "DistUpgradeConfigParser.py" ] class TestPyflakesClean(unittest.TestCase): """ ensure that the tree is pyflakes clean """ def test_pyflakes_clean(self): basepath = os.path.join(os.path.dirname(__file__), "..") for path, dirnames, filenames in os.walk(basepath): for name in filenames: if name.endswith(".py") and not name in PYFLAKES_BLACKLIST: pyfile = os.path.join(path, name) self.assertEqual(subprocess.call(["pyflakes", pyfile]), 0) if __name__ == "__main__": unittest.main() auto-upgrade-testing/bin/0000775000000000000000000000000012076525005012570 5ustar auto-upgrade-testing/bin/auto-install-tester0000775000000000000000000001774512076525005016454 0ustar #!/usr/bin/python3 from __future__ import absolute_import, print_function from optparse import OptionParser import os import sys import time # check if we run from a bzr checkout if os.path.exists("AutoUpgradeTester"): sys.path.insert(0, ".") from AutoUpgradeTester.UpgradeTestBackendQemu import UpgradeTestBackendQemu import apt import apt_pkg def do_install_remove(backend, pkgname): """ install a package in the backend """ #print("watchdog_runing: ", backend.watchdog_running) if not backend.watchdog_running: print("starting watchdog") backend._runInImage(["/bin/apt-watchdog"]) backend.watchdog_running = True # ret = backend._runInImage(["DEBIAN_FRONTEND=text","DEBIAN_PRIORITY=low", # "apt-get","install","-q","-y",pkg.name]) ret = backend._runInImage(["DEBIAN_FRONTEND=noninteractive", "apt-get","install","-q","-y",pkg.name]) print("apt returned: ", ret) if ret != 0: return False # now remove it again ret = backend._runInImage(["DEBIAN_FRONTEND=noninteractive", "apt-get","autoremove", "-y",pkg.name]) print("apt returned: ", ret) if ret != 0: return False return True def test_downloadable(backend, pkgname): """ test if the pkg is downloadable or gives a 404 """ ret = backend._runInImage(["apt-get","install","-q","--download-only","-y",pkg.name]) print("apt --download-only returned: ", ret) if ret != 0: return False return True if __name__ == "__main__": parser = OptionParser() parser.add_option("-p", "--profile", dest="profile", default="profile/auto-install-tester/", help="base profile dir") (options, args) = parser.parse_args() # create backend apt_pkg.config.set("APT::Architecture","i386") basedir = os.path.abspath(os.path.dirname(options.profile)) aptbasedir = os.path.join(basedir,"auto-install-test") # create apt dirs if needed for d in ["etc/apt/", "var/lib/dpkg", "var/lib/apt/lists/partial", "var/cache/apt/archives/partial"]: if not os.path.exists(os.path.join(aptbasedir,d)): os.makedirs(os.path.join(aptbasedir,d)) backend = UpgradeTestBackendQemu(options.profile) backend.watchdog_running = False backend.bootstrap() # copy status file from image to aptbasedir backend.start() print("copy apt-watchdog") if os.path.exists("share/script/apt-watchdog"): backend._copyToImage("share/scripts/apt-watchdog", "/bin/") else: backend._copyToImage("/usr/share/auto-upgrade-tester/scripts/apt-watchdog", "/bin/") print("copy status file") backend._copyFromImage("/var/lib/dpkg/status", os.path.join(aptbasedir,"var/lib/dpkg/","status")) print("run update") backend._runInImage(["apt-get","-q", "update"]) backend.stop() # build apt stuff (outside of the kvm) mirror = backend.config.get("NonInteractive","Mirror") dist = backend.config.get("Sources","From") components = backend.config.getlist("NonInteractive","Components") pockets = backend.config.getlist("NonInteractive","Pockets") f=open(os.path.join(aptbasedir,"etc","apt","sources.list"),"w") f.write("deb %s %s %s\n" % (mirror, dist, " ".join(components))) for pocket in pockets: f.write("deb %s %s-%s %s\n" % (mirror, dist, pocket, " ".join(components))) f.close() # get a cache cache = apt.Cache(rootdir=os.path.abspath(aptbasedir)) cache.update(apt.progress.text.AcquireProgress()) cache.open(apt.progress.base.OpProgress()) # now test if we can install stuff backend.saveVMSnapshot("clean-base") backend.start() # setup dirs resultdir = backend.resultdir print("Using resultdir: '%s'" % resultdir) failures = open(os.path.join(resultdir,"failures.txt"),"w") # pkg blacklist - only useful for pkg that causes exsessive delays # when installing, e.g. by requiring input or by tryint to connect # to a (firewalled) network pkgs_blacklisted = set() sname = os.path.join(resultdir,"pkgs_blacklisted.txt") print("looking at ", sname) if os.path.exists(sname): pkgs_blacklisted = set(open(sname).read().split("\n")) print("have '%s' with '%i' entries" % (sname, len(pkgs_blacklisted))) # set with package that have been tested successfully pkgs_tested = set() sname = os.path.join(resultdir,"pkgs_done.txt") print("looking at ", sname) if os.path.exists(sname): pkgs_tested = set(open(sname).read().split("\n")) print("have '%s' with '%i' entries" % (sname, len(pkgs_tested))) statusfile = open(sname, "a") else: statusfile = open(sname, "w") # now see if we can install and remove it again for (i, pkg) in enumerate(cache): # for (i, pkg) in enumerate([ cache["abook"], # cache["emacspeak"], # cache["postfix"] ]): # clean the cache cache._depcache.init() print("\n\nPackage %s: %i of %i (%f.2)" % (pkg.name, i, len(cache), float(i)/float(len(cache))*100)) print("pkgs_tested has %i entries\n\n" % len(pkgs_tested)) pkg_failed = False if not pkg.candidate: continue # skip stuff in the ubuntu-minimal that we can't install or upgrade if pkg.is_installed and not pkg.is_upgradable: continue # skip blacklisted pkg names if pkg.name in pkgs_blacklisted: print("blacklisted: ", pkg.name) continue # skip packages we tested already if "%s-%s" % (pkg.name, pkg.candidate.version) in pkgs_tested: print("already tested: ", pkg.name) continue # see if we can install/upgrade the pkg try: pkg.mark_install() except SystemError as e: pkg.mark_keep() if not (pkg.marked_install or pkg.marked_upgrade): print("pkg: %s not installable" % pkg.name) failures.write("%s mark_install()\n " % pkg.name) continue if not test_downloadable(backend, pkg.name): # because the test runs for so long its likely that we hit # 404 because the archive has changed since we ran, deal with # that here by not outputing it as a error for a start # FIXME: restart whole test continue # mark as tested statusfile.write("%s-%s\n" % (pkg.name, pkg.candidate.version)) if not do_install_remove(backend, pkg.name): # on failure, re-run in a clean env so that the log # is more meaningful print("pkg: %s failed, re-testing in a clean(er) environment" % pkg.name) backend.restoreVMSnapshot("clean-base") backend.watchdog_running = False backend.start() if not do_install_remove(backend, pkg.name): outname = os.path.join(resultdir,"%s-fail.txt" % pkg.name) failures.write("failed to install/remove %s (log at %s)\n" % (pkg.name, outname)) time.sleep(5) backend._copyFromImage("/var/log/apt/term.log",outname) # now restore back to a clean state and continue testing # (but do not record the package as succesful tested) backend.restoreVMSnapshot("clean-base") backend.watchdog_running = False backend.start() continue # installation worked, record that we have tested this package for pkg in cache: if pkg.marked_install or pkg.marked_upgrade: pkgs_tested.add("%s-%s" % (pkg.name, pkg.candidate.version)) statusfile.flush() failures.flush() # all done, stop the backend backend.stop() auto-upgrade-testing/bin/auto-upgrade-tester-jenkins-slave0000775000000000000000000000402212076525005021164 0ustar #!/usr/bin/python3 # # Copyright (C) 2010, Canonical Ltd (http://www.canonical.com/) # # This file is part of ubuntu-server-iso-testing. # # ubuntu-server-iso-testing is free software: you can redistribute it # and/or modify it under the terms of the GNU General Public License # as published by the Free Software Foundation, version 3 of # the License. # # ubuntu-server-iso-testing is distributed in the hope that it will # be useful, but WITHOUT ANY WARRANTY; without even the implied warranty # of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with ubuntu-server-iso-testing. If not, see # . # import logging import optparse import os try: from urllib.request import urlretrieve except ImportError: from urllib import urlretrieve import sys import subprocess import socket usage="usage: %prog [options] HUDSON_URL" parser = optparse.OptionParser(usage=usage) parser.add_option("-d", "--debug", dest="debug", action="store_true", default=False, help="enable debugging") parser.add_option("-n", "--nodename", dest="nodename", default=socket.gethostname(), help="hostname to use when registering with hudson (default=hostname)") (options, args) = parser.parse_args() if len(args) == 0: logging.error("Need a HUDSON_URL to execute") parser.print_help() sys.exit(1) if options.debug: logging.basicConfig(level=logging.DEBUG) else: logging.basicConfig(level=logging.INFO) HUDSON_URL=args[0] HUDSON_PATH="/computer/%s/slave-agent.jnlp" SLAVE_URL=HUDSON_URL + 'jnlpJars/slave.jar' SLAVE_JAR=os.path.expanduser("~/.slave.jar") l_hudson_url= HUDSON_URL + HUDSON_PATH % options.nodename logging.debug("Retrieving hudson slave.jar") urlretrieve(SLAVE_URL, SLAVE_JAR) cmd = [ 'java','-jar', SLAVE_JAR, '-jnlpUrl', l_hudson_url ] logging.debug("Cmd: %s" % (cmd)) subprocess.check_call(cmd) auto-upgrade-testing/bin/auto-upgrade-tester0000775000000000000000000003547112076525005016431 0ustar #!/usr/bin/python3 -u # "-u": Force stdin, stdout and stderr to be totally unbuffered. # To get more accurate log files # # see also # http://www.faqts.com/knowledge_base/entry/versions/index.phtml?aid=4419 from __future__ import print_function import datetime import glob import logging import multiprocessing import os import shutil import sys import time import subprocess import codecs try: from configparser import SafeConfigParser except ImportError: from ConfigParser import SafeConfigParser # check if we run from a bzr checkout if os.path.exists("AutoUpgradeTester"): sys.path.insert(0, ".") from optparse import OptionParser from AutoUpgradeTester.UpgradeTestBackend import UpgradeTestBackend # bigger exitcode means more problematic error, # exitcode 101 means generic error class FailedToBootstrapError(Exception): """ Failed to initial bootstrap the test system """ exitcode = 99 class FailedToUpgradeError(Exception): """ Failed to upgrade the test system """ exitcode = 98 class FailedPostUpgradeTestError(Exception): """ Some post upgrade tests failed """ exitcode = 97 class OutputThread(multiprocessing.Process): def __init__(self, filename): multiprocessing.Process.__init__(self) self.file = codecs.open(filename, 'r', 'utf-8') if sys.version_info < (3, 0): self.output = sys.stdout.write else: self.output = sys.stdout.buffer.write def run(self): while True: # the read() seems to not block for some reason # but return "" ?!? s = self.file.read(1024) if s: self.output(s.encode('utf-8')) else: time.sleep(0.1) # FIXME: move this into the generic backend code def login(backend): """ login into a backend """ backend.bootstrap() backend.login() def createBackend(backend_name, profile): """ create a backend of the given name for the given profile """ try: backend_full_name = "AutoUpgradeTester.%s" % backend_name backend_modul = __import__(backend_full_name, globals(), fromlist="AutoUpgradeTester") backend_class = getattr(backend_modul, backend_name) except (ImportError, AttributeError, TypeError) as e: logging.exception("can not import '%s'" % backend_name) return None return backend_class(profile) class HtmlOutputStream: HTML_HEADER=r""" Auto upgrade tester

Automatic upgrade tester test results

Upgrade test started %(date)s

""" HTML_FOOTER="""
ProfileResultBugsDate FinishedRuntimeFull Logs

Upgrade test finished %s

""" def __init__(self, outputdir=None): self.html_output = None if outputdir: self.outputdir = outputdir if not os.path.exists(outputdir): os.makedirs(outputdir) self.html_output = open(os.path.join(outputdir, "index.html"), "w") def write(self, s): if self.html_output: self.html_output.write(s) self.html_output.flush() def copy_results_and_add_table_link(self, profile_name, resultdir): if not self.html_output: return # copy logs & sanitize permissions targetdir = os.path.join(self.outputdir, profile_name) html_output.copytree(resultdir, targetdir) for f in glob.glob(targetdir+"/*"): os.chmod(f, 0o644) # write html line that links to output dir s = "Logs for %(profile)s test" % { 'logdir' : profile_name, 'profile': profile_name, } html_output.write(s) def copytree(self, src, dst): if self.html_output: shutil.copytree(src, dst) def write_html_header(self, time_started): self.write(self.HTML_HEADER % { 'date' : time_started }) def write_html_footer(self): self.write(self.HTML_FOOTER % datetime.datetime.now()) def testUpgrade(backend_name, profile, add_pkgs, quiet=False, html_output=HtmlOutputStream()): """ test upgrade for the given backend/profile """ backend = createBackend(backend_name, profile) assert(backend != None) if not os.path.exists(profile): print("ERROR: Can't find '%s' " % profile) html_output.write("Can't find profile '%s'" % profile) html_output.write(4*"") return 2 print("Storing the result in '%s'" % backend.resultdir) profile_name = os.path.split(os.path.normpath(profile))[1] # setup output outfile = os.path.join(backend.resultdir, "bootstrap.log") fd = os.open(outfile, os.O_WRONLY|os.O_CREAT|os.O_TRUNC, 0o644) out = OutputThread(outfile) out.daemon = True if not quiet: out.start() old_stdout = os.dup(1) old_stderr = os.dup(2) os.dup2(fd, 1) os.dup2(fd, 2) time_started = datetime.datetime.now() print("%s log started" % time_started) result = 0 try: # write what we working on html_output.write("%s" % profile_name) # init if not backend.bootstrap(): print("FAILED: bootstrap for '%s'" % profile) html_output.write("Failed to bootstrap") raise FailedToBootstrapError("Failed to bootstrap '%s'" % profile) if add_pkgs: if not backend.installPackages(add_pkgs): print("FAILED: installPacakges '%s'" % add_pkgs) html_output.write("Failed to add pkgs '%s'" % ",".join(add_pkgs)) raise Exception("Failed to install packages '%s'" % add_pkgs) if not backend.upgrade(): print("FAILED: upgrade for '%s'" % profile) html_output.write("Failed to upgrade") raise FailedToUpgradeError("Failed to upgrade %s" % profile) if not backend.test(): print("FAILED: test for '%s'" % profile) html_output.write("Upgraded, but post upgrade test failed") raise FailedPostUpgradeTestError("Failed in post upgrade test %s" % profile) print("profile: %s worked" % profile) html_output.write("ok") except (FailedToBootstrapError, FailedToUpgradeError, FailedPostUpgradeTestError) as e: print(e) result = e.exitcode except Exception as e: import traceback traceback.print_exc() print("Caught exception in testUpgrade for '%s' (%s)" % (profile, e)) html_output.write("Unknown failure (should not happen)") result = 2 finally: # print out result details print("Logs can be found here:") for n in ["bootstrap.log", "main.log", "apt.log"]: print(" %s/%s" % (backend.resultdir, n)) time_ended = datetime.datetime.now() print("%s log ended." % time_ended) print("Duration: %s" % (time_ended - time_started)) # give the output time to settle and kill the daemon time.sleep(2) if out.is_alive(): out.terminate() out.join() # write result line s="%(date)s%(runtime)s" % { 'date' : datetime.datetime.now(), 'runtime' : datetime.datetime.now() - time_started} html_output.write(s) html_output.copy_results_and_add_table_link(profile_name, backend.resultdir) html_output.write("") # close and restore file descriptors os.close(fd) os.dup2(old_stdout, 1) os.dup2(old_stderr, 2) return result def profileFromAptClone(aptclonefile): """ Create a profile from an apt-clone archive :param aptclonefile: Path to an apt-clone archive :return: path to profile or None if it fails to recognize the clone file """ profile = None try: cmd = ('apt-clone', 'info', aptclonefile) output = subprocess.check_output(cmd, universal_newlines=True) clone_properties = {} for k, v in [ line.split(': ') for line in output.split('\n') if ': ' in line]: clone_properties[k] = v try: clone_date = datetime.datetime.strptime(clone_properties['Date'], '%c').strftime('_%Y%m%d-%H%M%S') except: clone_date = '' profilename = "%s_%s_%s%s" % ( clone_properties['Distro'], clone_properties['Arch'], clone_properties['Hostname'], clone_date) # Generate configuration file for this profile # FIXME: # update packaging to grant write access on base for upgrade-tester user ppath = 'profile' if os.path.exists("./UpgradeTestBackend.py") else base profile = os.path.join(ppath, profilename) profilecfg = SafeConfigParser() if not os.path.exists(profile): os.makedirs(profile) profilecfg.set('DEFAULT', 'SourceRelease', clone_properties['Distro']) profilecfg.add_section('NonInteractive') profilecfg.set('NonInteractive', 'ProfileName', profilename) profilecfg.set('NonInteractive', 'AptcloneFile', os.path.abspath(aptclonefile)) profilecfg.add_section('KVM') profilecfg.set('KVM', 'Arch', clone_properties['Arch']) with open(os.path.join(profile, 'DistUpgrade.cfg'), 'wb') as profilefile: profilecfg.write(profilefile) except subprocess.CalledProcessError: return None return profile if __name__ == "__main__": logging.basicConfig(level=logging.INFO) parser = OptionParser() parser.add_option("--additinoal", "--additional-pkgs", dest="add_pkgs", default="", help="add additional pkgs before running the upgrade") parser.add_option("-a", "--auto", dest="auto", default=False, action="store_true", help="run all tests in profile/ dir") parser.add_option("--bootstrap-only", "--bootstrap-only",dest="bootstrap_only", default=False, action="store_true", help="only bootstrap the image") parser.add_option("--tests-only", "", default=False, action="store_true", help="only run post_upgrade_tests in the image") parser.add_option("-l", "--login", dest="login", default=False, action="store_true", help="log into the a profile") parser.add_option("-b", "--backend", dest="backend", default="UpgradeTestBackendQemu", help="UpgradeTestBackend to use: UpgradeTestBackendChroot, UpgradeTestBackendQemu") parser.add_option("-d", "--diff", dest="gen_diff", default=False, action="store_true", help="generate a diff of the upgraded image versus a fresh installed image") parser.add_option("--quiet", "--quiet", default=False, action="store_true", help="quiet operation") parser.add_option("", "--html-output-dir", default=None, help="html output directory") parser.add_option("", "--data-dir", default="/usr/share/auto-upgrade-tester/", help="directory with the profiles") (options, args) = parser.parse_args() # save for later fd1 = os.dup(1) fd2 = os.dup(2) # set basedir from datadir base = os.path.join(options.data_dir, "profiles") # check if we have something to do profiles = args if not profiles and not options.auto: print(sys.argv[0]) print("No profile specified, available default profiles:") print("\n".join(os.listdir(base))) print() print("Or use '-a' for 'auto' mode") sys.exit(1) # generic res = 0 add_pkgs = [] if options.add_pkgs: add_pkgs = options.add_pkgs.split(",") # auto mode if options.auto: print("running in auto-mode") for d in os.listdir(base): os.dup2(fd1, 1) os.dup2(fd2, 2) print("Testing '%s'" % d) res = max(res, testUpgrade(options.backend, base+d, add_pkgs)) sys.exit(res) # profile mode, test the given profiles time_started = datetime.datetime.now() # clean output dir html_output = HtmlOutputStream(options.html_output_dir) html_output.write_html_header(time_started) for profile in profiles: # case of an apt-clone archive if os.path.isfile(profile): profilename = profileFromAptClone(profile) if not profilename: print("File is not a valid apt-clone image: %s" % profilename) continue profile = profilename print("Using generated profile: %s" % profile) if not "/" in profile: profile = base + profile try: if options.login: backend = createBackend(options.backend, profile) login(backend) elif options.bootstrap_only: backend = createBackend(options.backend, profile) backend.bootstrap(force=True) elif options.tests_only: backend = createBackend(options.backend, profile) backend.test() elif options.gen_diff: backend = createBackend(options.backend, profile) backend.genDiff() else: print("Testing '%s'" % profile) now = datetime.datetime.now() current_res = testUpgrade(options.backend, profile, add_pkgs, options.quiet, html_output) if current_res == 0: print("Profile '%s' worked" % profile) else: print("Profile '%s' FAILED" % profile) res = max(res, current_res) except Exception as e: import traceback print("ERROR: exception caught '%s' " % e) html_output.write('
unhandled ERROR %s:\n%s
' % (e, traceback.format_exc())) traceback.print_exc() if hasattr(e, "exitcode"): res = max(res, e.exitcode) else: res = max(res, 101) html_output.write_html_footer() # return exit code sys.exit(res) auto-upgrade-testing/TODO0000664000000000000000000000017512076525005012513 0ustar * Add back the possibility to run with update-manager from bzr * Move all test to python unittest * Clean-up deprecated code auto-upgrade-testing/setup.py0000775000000000000000000000102312076525005013531 0ustar #!/usr/bin/python3 from distutils.core import setup import glob import os def data_files(): data_files = [] for root, dirs, files in os.walk('share'): if files: files = [ "%s/%s" % (root, file) for file in files ] data_files.append((root.replace('share', 'share/auto-upgrade-tester'),files)) return data_files setup(name='auto-upgrade-testing', packages=['AutoUpgradeTester'], package_dir={'': '.'}, scripts=glob.glob("bin/*"), data_files=data_files() ) auto-upgrade-testing/AUTHORS0000664000000000000000000000014212076525005013065 0ustar Hackers ======= Michael Vogt Stéphane Graber auto-upgrade-testing/README0000664000000000000000000000133012076525005012675 0ustar This code will test a release upgrade. If its started and there is a dir/symlink called "DistUpgrade" this code will be used for the upgrade (useful for testing the bzr development version of the upgrader code). Otherwise the latest released version of the archive is used via "do-release-upgrade". Installation ============ See https://wiki.ubuntu.com/QATeam/UpgradeTestingSetup for information on how to setup your host system for running auto-upgrade-tester Running auto-upgrade-tester =========================== Run with e.g.: $ sudo ./bin/auto-upgrade-tester ./share/profiles/server or modify share/profiles/defaults.cfg.d/defaults.cfg and setup a new AutoUpgradeTesterBaseDir if you want to run it without sudo. auto-upgrade-testing/COPYING0000664000000000000000000010451312076525005013057 0ustar GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for them if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs, and that you know you can do these things. To protect your rights, we need to prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read . auto-upgrade-testing/debian/0000775000000000000000000000000012076525734013253 5ustar auto-upgrade-testing/debian/auto-upgrade-tester.auto-upgrade-tester-jenkins-slave.default0000664000000000000000000000051412076525005027160 0ustar # init configuration script for hudson-slave # User and Group to execute slave daemon asa # defaults to the ubuntu server iso testing # account as part of this package USER=upgrade-tester GROUP=nogroup # URL to access Hudson Master Server HUDSON_MASTER= # Options to pass to hudson-slave # OPTS="-d" # Run at startup STARTUP=false auto-upgrade-testing/debian/copyright0000664000000000000000000000204712076525005015200 0ustar Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ Upstream-Name: Auto Upgrade Testing Source: https://code.launchpad.net/~auto-upgrade-testing-dev/auto-upgrade-testing/trunk Files: * Copyright: 2004-2012 Canonical Ltd. License: GPL-3 Files: debian/* Copyright: 2004-2012 Canonical Ltd. License: GPL-3 License: GPL-3 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 3 of the License. . This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. . You should have received a copy of the GNU General Public License along with this program. If not, see . . On Debian systems, the full text of the GNU General Public License version 3 can be found in the file /usr/share/common-licenses/GPL-3. auto-upgrade-testing/debian/auto-upgrade-tester.postinst0000664000000000000000000000040112076525005020743 0ustar #!/bin/sh set -e . /usr/share/debconf/confmodule case "$1" in configure) if which adduser >/dev/null 2>&1; then adduser --system --quiet --no-create-home upgrade-tester > /dev/null || true fi ;; esac #DEBHELPER# exit 0 auto-upgrade-testing/debian/source/0000775000000000000000000000000012076525005014542 5ustar auto-upgrade-testing/debian/source/format0000664000000000000000000000001512076525005015751 0ustar 3.0 (native) auto-upgrade-testing/debian/changelog0000664000000000000000000000501612076525734015127 0ustar auto-upgrade-testing (1:0.166) raring; urgency=low [ Adam Conrad ] * Prefer qemu-system (>= 1.3.0) over kvm for the new qemu packages, but keep the alternate dependencies in place for backport users. [ Paul Larson ] * Don't report obsolete config files as failure. [ Stéphane Graber ] * Replace builtin lxc.py module by the proper python3-lxc upstream module (a backport exists in precise-backports for 12.04 users). -- Adam Conrad Sat, 19 Jan 2013 07:14:51 -0700 auto-upgrade-testing (1:0.165) raring-proposed; urgency=low [ Michael Vogt ] * add --data-dir=./share argument to make running from the branch easier * pyflake clean * add pyflakes test * depend/build-depend on python3-distupgrade to get the imported versions of DistUpgradeConfigParser.py and utils.py instead of copies of it * AutoUpgradeTester/UpgradeTestBackendQemu.py: - use the dpkg force-unsafe-io option to make stuff fast [ Dmitrijs Ledkovs ] * Fix Vcs-Bzr URL to be usable with debcheckout * As there are no python specific paths/symlinks, arch:all packages should simply build against python3, have correct forward looking X-Python3-Version and use python3 as shebang. All fixed now, and ready for smooth no-rebuild python3.3 by default transition. -- Dmitrijs Ledkovs Wed, 24 Oct 2012 22:52:20 +0100 auto-upgrade-testing (1:0.164) quantal; urgency=low * share/post_upgrade_tests/test_python_import.py: Fix CalledProcessError crash when a python module is not shipped by any package any more. * share/post_upgrade_tests/test_python_import.py: Run test under xvfb, so that modules that need a $DISPLAY (such as ccsm) will not fail. Add xvfb dependency for this. (LP: #1024346) -- Martin Pitt Fri, 13 Jul 2012 16:14:37 +0200 auto-upgrade-testing (1:0.163) quantal; urgency=low [ Michael Terry ] * Initial packaging, adapted from update-manager. * Move binary package auto-upgrade-tester from update-manager source package to this new source. * Open temporary files in text mode (LP: #1021820). [ Colin Watson ] * Port to python3 [ Stéphane Graber ] * Restructure source branch, move all the scripts, profiles, post-upgrade hooks and any other file to /usr/share/auto-upgrade-tester * Add new LXC backend. * Port any remaining code to python3. [ Michael Vogt ] * Set default to precise -> quantal upgrade. -- Stéphane Graber Wed, 13 Jun 2012 19:33:12 -0400 auto-upgrade-testing/debian/compat0000664000000000000000000000000212076525005014440 0ustar 9 auto-upgrade-testing/debian/rules0000775000000000000000000000053512076525005014325 0ustar #!/usr/bin/make -f %: dh $@ --with=python3 override_dh_auto_clean: dh_auto_clean rm -rf build override_dh_auto_build: python3 setup.py build override_dh_auto_install: python3 setup.py install --root=$(CURDIR)/debian/auto-upgrade-tester --install-layout=deb override_dh_installinit: dh_installinit --name=auto-upgrade-tester-jenkins-slave auto-upgrade-testing/debian/control0000664000000000000000000000210612076525126014650 0ustar Source: auto-upgrade-testing Section: devel Priority: optional Maintainer: Ubuntu Developers Build-Depends: debhelper (>= 9), python3, python3-distupgrade Standards-Version: 3.9.3 Homepage: https://launchpad.net/auto-upgrade-testing Vcs-Bzr: https://code.launchpad.net/~auto-upgrade-testing-dev/auto-upgrade-testing/trunk X-Python3-Version: >= 3.2 Package: auto-upgrade-tester Architecture: all Depends: ${misc:Depends}, ${python3:Depends}, python3-apt, python3-update-manager (>=1:0.163~), python3-distupgrade, lsb-release Recommends: qemu-system (>= 1.3.0) | qemu-kvm | kvm, ubuntu-vm-builder, python3-lxc Suggests: default-jre-headless | java2-runtime-headless, lxc Description: Test release upgrades in a virtual environment A tool to do QA for release upgrades in ubuntu that performs upgrades in a virtual environment. Supported backends are "chroot", "kvm", "lxc" and "EC2". It will also install a hudson/jenkins slave (disabled by default). auto-upgrade-testing/debian/auto-upgrade-tester.auto-upgrade-tester-jenkins-slave.upstart0000664000000000000000000000166612076525005027247 0ustar # Hudson Slave description "auto-upgrade-tester-jenkins-slave: distributed job control" author "James Page " start on (local-filesystems and net-device-up IFACE!=lo) stop on runlevel [!2345] pre-start script . /etc/default/auto-upgrade-tester-jenkins-slave test -x /usr/bin/auto-upgrade-tester-jenkins-slave || { stop ; exit 0; } test -r /etc/default/auto-upgrade-tester-jenkins-slave || { stop ; exit 0; } test "${STARTUP}" = "true" || { stop; exit 0; } end script script . /etc/default/auto-upgrade-tester-jenkins-slave JDK_DIRS="/usr/lib/jvm/java-6-openjdk /usr/lib/jvm/java-6-sun" for jdir in $JDK_DIRS; do if [ -r "$jdir/bin/java" -a -z "${JAVA_HOME}" ]; then JAVA_HOME="$jdir" fi done export JAVA_HOME exec start-stop-daemon --start --chuid $USER:$GROUP --exec /usr/bin/auto-upgrade-tester-jenkins-slave -- $OPTS $HUDSON_MASTER end script auto-upgrade-testing/debian/docs0000664000000000000000000000002412076525005014111 0ustar README TODO AUTHORS auto-upgrade-testing/debian/auto-upgrade-tester.postrm0000664000000000000000000000034312076525005020411 0ustar #!/bin/sh set -e . /usr/share/debconf/confmodule case "$1" in purge) if which deluser >/dev/null 2>&1; then deluser --quiet upgrade-tester > /dev/null || true fi ;; esac #DEBHELPER# exit 0