class TestDebianInstaller(TestCase): def setUp(self): super(TestDebianInstaller, self).setUp() self.temp_dir = self.makeTemporaryDirectory() self.pubconf = FakeConfig(self.temp_dir) self.suite = "distroseries" # CustomUpload.installFiles requires a umask of 022. old_umask = os.umask(022) self.addCleanup(os.umask, old_umask) def openArchive(self): self.version = "20070214ubuntu1" self.arch = "i386" self.path = os.path.join( self.temp_dir, "debian-installer-images_%s_%s.tar.gz" % (self.version, self.arch)) self.buffer = open(self.path, "wb") self.archive = LaunchpadWriteTarFile(self.buffer) def addFile(self, path, contents): self.archive.add_file( "installer-%s/%s/%s" % (self.arch, self.version, path), contents) def addSymlink(self, path, target): self.archive.add_symlink( "installer-%s/%s/%s" % (self.arch, self.version, path), target) def process(self): self.archive.close() self.buffer.close() process_debian_installer(self.pubconf, self.path, self.suite) def getInstallerPath(self, versioned_filename=None): installer_path = os.path.join( self.temp_dir, "dists", self.suite, "main", "installer-%s" % self.arch) if versioned_filename is not None: installer_path = os.path.join( installer_path, self.version, versioned_filename) return installer_path def test_basic(self): # Processing a simple correct tar file succeeds. self.openArchive() self.addFile("hello", "world") self.process() def test_already_exists(self): # If the target directory already exists, processing fails. self.openArchive() os.makedirs(self.getInstallerPath(".")) self.assertRaises(CustomUploadAlreadyExists, self.process) def test_bad_umask(self): # The umask must be 022 to avoid incorrect permissions. self.openArchive() self.addFile("dir/file", "foo") os.umask(002) # cleanup already handled by setUp self.assertRaises(CustomUploadBadUmask, self.process) def test_current_symlink(self): # A "current" symlink is created to the last version. self.openArchive() self.addFile("hello", "world") self.process() installer_path = self.getInstallerPath() self.assertContentEqual( [self.version, "current"], os.listdir(installer_path)) self.assertEqual( self.version, os.readlink(os.path.join(installer_path, "current"))) def test_correct_file(self): # Files in the tarball are extracted correctly. self.openArchive() directory = ("images/netboot/ubuntu-installer/i386/" "pxelinux.cfg.serial-9600") filename = os.path.join(directory, "default") long_filename = os.path.join( directory, "very_very_very_very_very_very_long_filename") self.addFile(filename, "hey") self.addFile(long_filename, "long") self.process() with open(self.getInstallerPath(filename)) as f: self.assertEqual("hey", f.read()) with open(self.getInstallerPath(long_filename)) as f: self.assertEqual("long", f.read()) def test_correct_symlink(self): # Symbolic links in the tarball are extracted correctly. self.openArchive() foo_path = "images/netboot/foo" foo_target = "ubuntu-installer/i386/pxelinux.cfg.serial-9600/default" link_to_dir_path = "images/netboot/link_to_dir" link_to_dir_target = "ubuntu-installer/i386/pxelinux.cfg.serial-9600" self.addSymlink(foo_path, foo_target) self.addSymlink(link_to_dir_path, link_to_dir_target) self.process() self.assertEqual( foo_target, os.readlink(self.getInstallerPath(foo_path))) self.assertEqual( link_to_dir_target, os.path.normpath(os.readlink( self.getInstallerPath(link_to_dir_path)))) def test_top_level_permissions(self): # Top-level directories are set to mode 0755 (see bug 107068). self.openArchive() self.addFile("hello", "world") self.process() installer_path = self.getInstallerPath() self.assertEqual(0755, os.stat(installer_path).st_mode & 0777) self.assertEqual( 0755, os.stat(os.path.join(installer_path, os.pardir)).st_mode & 0777) def test_extracted_permissions(self): # Extracted files and directories are set to 0644/0755. self.openArchive() directory = ("images/netboot/ubuntu-installer/i386/" "pxelinux.cfg.serial-9600") filename = os.path.join(directory, "default") self.addFile(filename, "hey") self.process() self.assertEqual( 0644, os.stat(self.getInstallerPath(filename)).st_mode & 0777) self.assertEqual( 0755, os.stat(self.getInstallerPath(directory)).st_mode & 0777) def test_getSeriesKey_extracts_architecture(self): # getSeriesKey extracts the architecture from an upload's filename. self.openArchive() self.assertEqual( self.arch, DebianInstallerUpload.getSeriesKey(self.path)) def test_getSeriesKey_returns_None_on_mismatch(self): # getSeriesKey returns None if the filename does not match the # expected pattern. self.assertIsNone(DebianInstallerUpload.getSeriesKey("argh_1.0.jpg")) def test_getSeriesKey_refuses_names_with_wrong_number_of_fields(self): # getSeriesKey requires exactly three fields. self.assertIsNone(DebianInstallerUpload.getSeriesKey( "package_1.0.tar.gz")) self.assertIsNone(DebianInstallerUpload.getSeriesKey( "one_two_three_four_5.tar.gz"))
class TestDebianInstaller(RunPartsMixin, TestCaseWithFactory): layer = ZopelessDatabaseLayer def setUp(self): super(TestDebianInstaller, self).setUp() self.temp_dir = self.makeTemporaryDirectory() self.distro = self.factory.makeDistribution() db_pubconf = getUtility(IPublisherConfigSet).getByDistribution( self.distro) db_pubconf.root_dir = unicode(self.temp_dir) self.archive = self.factory.makeArchive(distribution=self.distro, purpose=ArchivePurpose.PRIMARY) self.suite = "distroseries" # CustomUpload.installFiles requires a umask of 0o022. old_umask = os.umask(0o022) self.addCleanup(os.umask, old_umask) def openArchive(self): self.version = "20070214ubuntu1" self.arch = "i386" self.path = os.path.join( self.temp_dir, "debian-installer-images_%s_%s.tar.gz" % (self.version, self.arch)) self.buffer = open(self.path, "wb") self.tarfile = LaunchpadWriteTarFile(self.buffer) def addFile(self, path, contents): self.tarfile.add_file( "installer-%s/%s/%s" % (self.arch, self.version, path), contents) def addSymlink(self, path, target): self.tarfile.add_symlink( "installer-%s/%s/%s" % (self.arch, self.version, path), target) def process(self): self.tarfile.close() self.buffer.close() DebianInstallerUpload().process(self.archive, self.path, self.suite) def getInstallerPath(self, versioned_filename=None): pubconf = getPubConfig(self.archive) installer_path = os.path.join(pubconf.archiveroot, "dists", self.suite, "main", "installer-%s" % self.arch) if versioned_filename is not None: installer_path = os.path.join(installer_path, self.version, versioned_filename) return installer_path def test_basic(self): # Processing a simple correct tar file succeeds. self.openArchive() self.addFile("hello", b"world") self.process() def test_already_exists(self): # If the target directory already exists, processing fails. self.openArchive() os.makedirs(self.getInstallerPath(".")) self.assertRaises(CustomUploadAlreadyExists, self.process) def test_bad_umask(self): # The umask must be 0o022 to avoid incorrect permissions. self.openArchive() self.addFile("dir/file", b"foo") os.umask(0o002) # cleanup already handled by setUp self.assertRaises(CustomUploadBadUmask, self.process) def test_current_symlink(self): # A "current" symlink is created to the last version. self.openArchive() self.addFile("hello", b"world") self.process() installer_path = self.getInstallerPath() self.assertContentEqual([self.version, "current"], os.listdir(installer_path)) self.assertEqual(self.version, os.readlink(os.path.join(installer_path, "current"))) def test_correct_file(self): # Files in the tarball are extracted correctly. self.openArchive() directory = ("images/netboot/ubuntu-installer/i386/" "pxelinux.cfg.serial-9600") filename = os.path.join(directory, "default") long_filename = os.path.join( directory, "very_very_very_very_very_very_long_filename") self.addFile(filename, b"hey") self.addFile(long_filename, b"long") self.process() with open(self.getInstallerPath(filename)) as f: self.assertEqual("hey", f.read()) with open(self.getInstallerPath(long_filename)) as f: self.assertEqual("long", f.read()) def test_correct_symlink(self): # Symbolic links in the tarball are extracted correctly. self.openArchive() foo_path = "images/netboot/foo" foo_target = "ubuntu-installer/i386/pxelinux.cfg.serial-9600/default" link_to_dir_path = "images/netboot/link_to_dir" link_to_dir_target = "ubuntu-installer/i386/pxelinux.cfg.serial-9600" self.addSymlink(foo_path, foo_target) self.addSymlink(link_to_dir_path, link_to_dir_target) self.process() self.assertEqual(foo_target, os.readlink(self.getInstallerPath(foo_path))) self.assertEqual( link_to_dir_target, os.path.normpath( os.readlink(self.getInstallerPath(link_to_dir_path)))) def test_top_level_permissions(self): # Top-level directories are set to mode 0o755 (see bug 107068). self.openArchive() self.addFile("hello", b"world") self.process() installer_path = self.getInstallerPath() self.assertEqual(0o755, os.stat(installer_path).st_mode & 0o777) self.assertEqual( 0o755, os.stat(os.path.join(installer_path, os.pardir)).st_mode & 0o777) def test_extracted_permissions(self): # Extracted files and directories are set to 0o644/0o755. self.openArchive() directory = ("images/netboot/ubuntu-installer/i386/" "pxelinux.cfg.serial-9600") filename = os.path.join(directory, "default") self.addFile(filename, b"hey") self.process() self.assertEqual( 0o644, os.stat(self.getInstallerPath(filename)).st_mode & 0o777) self.assertEqual( 0o755, os.stat(self.getInstallerPath(directory)).st_mode & 0o777) def test_sign_with_external_run_parts(self): self.enableRunParts(distribution_name=self.distro.name) with open( os.path.join(self.parts_directory, self.distro.name, "sign.d", "10-sign"), "w") as f: f.write( dedent("""\ #! /bin/sh touch "$OUTPUT_PATH" """)) os.fchmod(f.fileno(), 0o755) self.openArchive() self.addFile("images/list", "a list") self.addFile("images/SHA256SUMS", "a checksum") self.process() self.assertThat(self.getInstallerPath("images"), DirContains(["list", "SHA256SUMS", "SHA256SUMS.gpg"])) def test_getSeriesKey_extracts_architecture(self): # getSeriesKey extracts the architecture from an upload's filename. self.openArchive() self.assertEqual(self.arch, DebianInstallerUpload.getSeriesKey(self.path)) def test_getSeriesKey_returns_None_on_mismatch(self): # getSeriesKey returns None if the filename does not match the # expected pattern. self.assertIsNone(DebianInstallerUpload.getSeriesKey("argh_1.0.jpg")) def test_getSeriesKey_refuses_names_with_wrong_number_of_fields(self): # getSeriesKey requires exactly three fields. self.assertIsNone( DebianInstallerUpload.getSeriesKey("package_1.0.tar.gz")) self.assertIsNone( DebianInstallerUpload.getSeriesKey("one_two_three_four_5.tar.gz"))