launchpad-reviewers team mailing list archive
-
launchpad-reviewers team
-
Mailing list archive
-
Message #15698
[Merge] lp:~stevenk/launchpad/destroy-manage-chroot into lp:launchpad
Steve Kowalik has proposed merging lp:~stevenk/launchpad/destroy-manage-chroot into lp:launchpad.
Requested reviews:
Launchpad code reviewers (launchpad-reviewers)
For more details, see:
https://code.launchpad.net/~stevenk/launchpad/destroy-manage-chroot/+merge/171210
Now that we have two methods exported over the API, IDistroArchSeries.{set,remove}Chroot(), this horrible script that requires shell access to a privileged machine can die horribly. Good riddance.
--
https://code.launchpad.net/~stevenk/launchpad/destroy-manage-chroot/+merge/171210
Your team Launchpad code reviewers is requested to review the proposed merge of lp:~stevenk/launchpad/destroy-manage-chroot into lp:launchpad.
=== removed file 'lib/lp/soyuz/scripts/chrootmanager.py'
--- lib/lp/soyuz/scripts/chrootmanager.py 2012-06-29 08:40:05 +0000
+++ lib/lp/soyuz/scripts/chrootmanager.py 1970-01-01 00:00:00 +0000
@@ -1,230 +0,0 @@
-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Chroot management utilities."""
-
-__metaclass__ = type
-
-__all__ = [
- 'ChrootManager',
- 'ChrootManagerError',
- 'ManageChrootScript',
- ]
-
-import os
-
-from zope.component import getUtility
-
-from lp.app.errors import NotFoundError
-from lp.services.helpers import filenameToContentType
-from lp.services.librarian.interfaces import ILibraryFileAliasSet
-from lp.services.librarian.interfaces.client import (
- ILibrarianClient,
- UploadFailed,
- )
-from lp.services.librarian.utils import copy_and_close
-from lp.soyuz.scripts.ftpmasterbase import (
- SoyuzScript,
- SoyuzScriptError,
- )
-
-
-class ChrootManagerError(Exception):
- """Any error generated during the ChrootManager procedures."""
-
-
-class ChrootManager:
- """Chroot actions wrapper.
-
- The 'distroarchseries' argument is mandatory and 'filepath' is
- optional.
-
- 'filepath' is required by some allowed actions as source or destination,
-
- ChrootManagerError will be raised if anything wrong occurred in this
- class, things like missing parameter or infrastructure pieces not in
- place.
- """
-
- allowed_actions = ['add', 'update', 'remove', 'get']
-
- def __init__(self, distroarchseries, filepath=None):
- self.distroarchseries = distroarchseries
- self.filepath = filepath
- self._messages = []
-
- def _upload(self):
- """Upload the self.filepath contents to Librarian.
-
- Return the respective ILibraryFileAlias instance.
- Raises ChrootManagerError if it could not be found.
- """
- try:
- fd = open(self.filepath)
- except IOError:
- raise ChrootManagerError('Could not open: %s' % self.filepath)
-
- flen = os.stat(self.filepath).st_size
- filename = os.path.basename(self.filepath)
- ftype = filenameToContentType(filename)
-
- try:
- alias_id = getUtility(ILibrarianClient).addFile(
- filename, flen, fd, contentType=ftype)
- except UploadFailed as info:
- raise ChrootManagerError("Librarian upload failed: %s" % info)
-
- lfa = getUtility(ILibraryFileAliasSet)[alias_id]
-
- self._messages.append(
- "LibraryFileAlias: %d, %s bytes, %s"
- % (lfa.id, lfa.content.filesize, lfa.content.md5))
-
- return lfa
-
- def _getPocketChroot(self):
- """Retrive PocketChroot record.
-
- Return the respective IPocketChroot instance.
- Raises ChrootManagerError if it could not be found.
- """
- pocket_chroot = self.distroarchseries.getPocketChroot()
- if pocket_chroot is None:
- raise ChrootManagerError(
- 'Could not find chroot for %s'
- % (self.distroarchseries.title))
-
- self._messages.append(
- "PocketChroot for '%s' (%d) retrieved."
- % (pocket_chroot.distroarchseries.title, pocket_chroot.id))
-
- return pocket_chroot
-
- def _update(self):
- """Base method for add and update action."""
- if self.filepath is None:
- raise ChrootManagerError('Missing local chroot file path.')
- alias = self._upload()
- return self.distroarchseries.addOrUpdateChroot(alias)
-
- def add(self):
- """Create a new PocketChroot record.
-
- Raises ChrootManagerError if self.filepath isn't set.
- Update of pre-existing PocketChroot record will be automatically
- handled.
- It's a bind to the self.update method.
- """
- pocket_chroot = self._update()
- self._messages.append(
- "PocketChroot for '%s' (%d) added."
- % (pocket_chroot.distroarchseries.title, pocket_chroot.id))
-
- def update(self):
- """Update a PocketChroot record.
-
- Raises ChrootManagerError if filepath isn't set
- Creation of non-existing PocketChroot records will be automatically
- handled.
- """
- pocket_chroot = self._update()
- self._messages.append(
- "PocketChroot for '%s' (%d) updated."
- % (pocket_chroot.distroarchseries.title, pocket_chroot.id))
-
- def remove(self):
- """Overwrite existing PocketChroot file to none.
-
- Raises ChrootManagerError if the chroot record isn't found.
- """
- pocket_chroot = self._getPocketChroot()
- self.distroarchseries.addOrUpdateChroot(None)
- self._messages.append(
- "PocketChroot for '%s' (%d) removed."
- % (pocket_chroot.distroarchseries.title, pocket_chroot.id))
-
- def get(self):
- """Download chroot file from Librarian and store."""
- pocket_chroot = self._getPocketChroot()
-
- if self.filepath is None:
- abs_filepath = os.path.abspath(pocket_chroot.chroot.filename)
- if os.path.exists(abs_filepath):
- raise ChrootManagerError(
- 'cannot overwrite %s' % abs_filepath)
- self._messages.append(
- "Writing to '%s'." % abs_filepath)
- local_file = open(pocket_chroot.chroot.filename, "w")
- else:
- abs_filepath = os.path.abspath(self.filepath)
- if os.path.exists(abs_filepath):
- raise ChrootManagerError(
- 'cannot overwrite %s' % abs_filepath)
- self._messages.append(
- "Writing to '%s'." % abs_filepath)
- local_file = open(abs_filepath, "w")
-
- if pocket_chroot.chroot is None:
- raise ChrootManagerError('Chroot was deleted.')
-
- pocket_chroot.chroot.open()
- copy_and_close(pocket_chroot.chroot, local_file)
-
-
-class ManageChrootScript(SoyuzScript):
- """`SoyuzScript` that manages chroot files."""
-
- usage = "%prog -d <distribution> -s <suite> -a <architecture> -f file"
- description = "Manage the chroot files used by the builders."
- success_message = "Success."
-
- def add_my_options(self):
- """Add script options."""
- SoyuzScript.add_distro_options(self)
- SoyuzScript.add_transaction_options(self)
- self.parser.add_option(
- '-a', '--architecture', dest='architecture', default=None,
- help='Architecture tag')
- self.parser.add_option(
- '-f', '--filepath', dest='filepath', default=None,
- help='Chroot file path')
-
- def mainTask(self):
- """Set up a ChrootManager object and invoke it."""
- if len(self.args) != 1:
- raise SoyuzScriptError(
- "manage-chroot.py <add|update|remove|get>")
-
- [action] = self.args
-
- series = self.location.distroseries
-
- try:
- distroarchseries = series[self.options.architecture]
- except NotFoundError as info:
- raise SoyuzScriptError("Architecture not found: %s" % info)
-
- # We don't want to have to force the user to confirm transactions
- # for manage-chroot.py, so disable that feature of SoyuzScript.
- self.options.confirm_all = True
-
- self.logger.debug(
- "Initializing ChrootManager for '%s'" % (distroarchseries.title))
- chroot_manager = ChrootManager(
- distroarchseries, filepath=self.options.filepath)
-
- if action in chroot_manager.allowed_actions:
- chroot_action = getattr(chroot_manager, action)
- else:
- self.logger.error(
- "Allowed actions: %s" % chroot_manager.allowed_actions)
- raise SoyuzScriptError("Unknown action: %s" % action)
-
- try:
- chroot_action()
- except ChrootManagerError as info:
- raise SoyuzScriptError(info)
- else:
- # Collect extra debug messages from chroot_manager.
- for debug_message in chroot_manager._messages:
- self.logger.debug(debug_message)
=== removed file 'lib/lp/soyuz/scripts/tests/test_chrootmanager.py'
--- lib/lp/soyuz/scripts/tests/test_chrootmanager.py 2012-03-27 13:38:04 +0000
+++ lib/lp/soyuz/scripts/tests/test_chrootmanager.py 1970-01-01 00:00:00 +0000
@@ -1,161 +0,0 @@
-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""ChrootManager facilities tests."""
-
-__metaclass__ = type
-
-import os
-import re
-import tempfile
-from unittest import TestCase
-
-import transaction
-from zope.component import getUtility
-
-from lp.registry.interfaces.distribution import IDistributionSet
-from lp.services.config import config
-from lp.soyuz.scripts.chrootmanager import (
- ChrootManager,
- ChrootManagerError,
- )
-from lp.testing.layers import LaunchpadZopelessLayer
-
-
-class TestChrootManager(TestCase):
- layer = LaunchpadZopelessLayer
- dbuser = config.archivepublisher.dbuser
-
- def setUp(self):
- """Setup the test environment and retrieve useful instances."""
- self.files_to_delete = []
- self.distribution = getUtility(IDistributionSet)['ubuntu']
- self.distroarchseries = self.distribution.currentseries['i386']
-
- def tearDown(self):
- """Clean up test environment and remove the test archive."""
- self._remove_files()
-
- def _create_file(self, filename, content=None):
- """Create a file in the system temporary directory.
-
- Annotate the path for posterior removal (see _remove_files)
- """
- filepath = os.path.join(tempfile.gettempdir(), filename)
- if content is not None:
- fd = open(filepath, "w")
- fd.write(content)
- fd.close()
-
- self.files_to_delete.append(filepath)
- return filepath
-
- def _remove_files(self):
- """Remove files during this test."""
- for filepath in self.files_to_delete:
- os.remove(filepath)
-
- self.files_to_delete = []
-
- def test_initialize(self):
- """Chroot Manager initialization"""
- chroot_manager = ChrootManager(self.distroarchseries)
-
- self.assertEqual(self.distroarchseries,
- chroot_manager.distroarchseries)
- self.assertEqual([], chroot_manager._messages)
-
- def test_add_and_get(self):
- """Adding new chroot and then retrieve it."""
- chrootfilepath = self._create_file('chroot.test', content="UHMMM")
- chrootfilename = os.path.basename(chrootfilepath)
-
- chroot_manager = ChrootManager(
- self.distroarchseries, filepath=chrootfilepath)
-
- chroot_manager.add()
- match = re.match(
- ("LibraryFileAlias: \d+, 5 bytes, "
- "5088e6471ab02d4268002f529a02621c"),
- chroot_manager._messages[0])
- self.assert_(match is not None,
- "chroot_manager message mismatch: %s" %
- chroot_manager._messages[0])
- self.assertEqual(
- ["PocketChroot for 'The Hoary Hedgehog Release for i386 (x86)' "
- "(1) added."], chroot_manager._messages[1:])
-
- pocket_chroot = self.distroarchseries.getPocketChroot()
- self.assertEqual(chrootfilename, pocket_chroot.chroot.filename)
-
- # required to turn librarian results visible.
- transaction.commit()
-
- dest = self._create_file('chroot.gotten')
-
- chroot_manager = ChrootManager(
- self.distroarchseries, filepath=dest)
-
- chroot_manager.get()
- self.assertEqual(
- ["PocketChroot for 'The Hoary Hedgehog Release for i386 (x86)' "
- "(1) retrieved.",
- "Writing to '/tmp/chroot.gotten'."], chroot_manager._messages)
-
- self.assertEqual(True, os.path.exists(dest))
-
- def test_update_and_remove(self):
- """Update existing chroot then remove it."""
- chrootfilepath = self._create_file('chroot.update', content="DUHHHH")
- chrootfilename = os.path.basename(chrootfilepath)
-
- chroot_manager = ChrootManager(
- self.distroarchseries, filepath=chrootfilepath)
-
- chroot_manager.update()
- match = re.match(
- ("LibraryFileAlias: \d+, 6 bytes, "
- "a4cd43e083161afcdf26f4324024d8ef"), chroot_manager._messages[0])
- self.assert_(match is not None,
- "chroot_manager message mismatch: %s" %
- chroot_manager._messages[0])
- self.assertEqual(
- ["PocketChroot for 'The Hoary Hedgehog Release for i386 (x86)' "
- "(1) updated."], chroot_manager._messages[1:])
-
- pocket_chroot = self.distroarchseries.getPocketChroot()
- self.assertEqual(chrootfilename, pocket_chroot.chroot.filename)
-
- # required to turn librarian results visible.
- transaction.commit()
-
- chroot_manager = ChrootManager(self.distroarchseries)
-
- chroot_manager.remove()
- self.assertEqual(
- ["PocketChroot for 'The Hoary Hedgehog Release for i386 (x86)' "
- "(1) retrieved.",
- "PocketChroot for 'The Hoary Hedgehog Release for i386 (x86)' "
- "(1) removed."], chroot_manager._messages)
-
- pocket_chroot = self.distroarchseries.getPocketChroot()
- self.assertEqual(None, pocket_chroot.chroot)
-
- def test_remove_fail(self):
- """Attempt to remove non-existent chroot will fail."""
- # Use a different distroarchseries in the sample data; this one
- # has no chroot.
- distroarchseries = self.distribution['warty']['hppa']
- chroot_manager = ChrootManager(distroarchseries)
-
- self.assertRaises(
- ChrootManagerError, chroot_manager.remove)
-
- def test_add_fail(self):
- """Attempt to add non-existent local chroot will fail."""
- chroot_manager = ChrootManager(
- self.distroarchseries,
- filepath='foo-bar')
-
- self.assertRaises(
- ChrootManagerError, chroot_manager.add)
=== removed file 'scripts/ftpmaster-tools/manage-chroot.py'
--- scripts/ftpmaster-tools/manage-chroot.py 2013-01-07 03:21:35 +0000
+++ scripts/ftpmaster-tools/manage-chroot.py 1970-01-01 00:00:00 +0000
@@ -1,15 +0,0 @@
-#!/usr/bin/python -S
-#
-# Copyright 2009-2012 Canonical Ltd. This software is licensed under the
-# GNU Affero General Public License version 3 (see the file LICENSE).
-
-"""Tool for adding, removing and replacing buildd chroots."""
-
-import _pythonpath
-
-from lp.soyuz.scripts.chrootmanager import ManageChrootScript
-
-
-if __name__ == '__main__':
- script = ManageChrootScript('manage-chroot', dbuser="fiera")
- script.lock_and_run()