Jeroen T. Vermeulen has proposed merging lp:~jtv/maas/commissioning-tarball 
into lp:maas.

Commit message:
Model method: create tar archive of all commissioning scripts.

Requested reviews:
  Launchpad code reviewers (launchpad-reviewers)

For more details, see:
https://code.launchpad.net/~jtv/maas/commissioning-tarball/+merge/137045

This was discussed with several people.  What you see here is just the model 
part: "give me a tar archive containing all commissioning scripts."  In all 
likelihood this will be a very small and simple tar file, but if it turns out 
to be large or expensive to produce, we can then worry about caching it (and 
where) and maybe compressing it (and where).  We should be able to manage those 
pretty transparently; there are no design warts to accommodate optimization.

The next step will be to provide this tarball on the metadata API.  If we ever 
want to specialize the tarballs for different kinds of nodes, the model method 
can sprout filtering parameters but the API won't change — the requesting 
node's identity is already an implicit part of every metadata request.


Jeroen
-- 
https://code.launchpad.net/~jtv/maas/commissioning-tarball/+merge/137045
Your team Launchpad code reviewers is requested to review the proposed merge of 
lp:~jtv/maas/commissioning-tarball into lp:maas.
=== modified file 'src/metadataserver/models/commissioningscript.py'
--- src/metadataserver/models/commissioningscript.py	2012-11-22 11:53:01 +0000
+++ src/metadataserver/models/commissioningscript.py	2012-11-29 20:52:44 +0000
@@ -15,14 +15,42 @@
     'CommissioningScript',
     ]
 
+from io import BytesIO
+import os.path
+import tarfile
 
 from django.db.models import (
     CharField,
+    Manager,
     Model,
     )
 from metadataserver import DefaultMeta
 from metadataserver.fields import BinaryField
 
+# Path prefix for commissioning scripts.  Commissioning scripts will be
+# extracted into this directory.
+ARCHIVE_PREFIX = "commissioning.d"
+
+
+class CommissioningScriptManager(Manager):
+    """Utility for the collection of `CommissioningScript`s."""
+
+    def get_archive(self):
+        """Produce a tar archive of all commissioning scripts.
+
+        Each of the scripts will be in the `ARCHIVE_PREFIX` directory.
+        """
+        binary = BytesIO()
+        tarball = tarfile.open(mode='w', fileobj=binary)
+        for script in self.all().order_by('name'):
+            path = os.path.join(ARCHIVE_PREFIX, script.name)
+            tarinfo = tarfile.TarInfo(name=path)
+            tarinfo.size = len(script.content)
+            tarball.addfile(tarinfo, BytesIO(script.content))
+        tarball.close()
+        binary.seek(0)
+        return binary.read()
+
 
 class CommissioningScript(Model):
     """User-provided commissioning script.
@@ -34,5 +62,7 @@
     class Meta(DefaultMeta):
         """Needed for South to recognize this model."""
 
+    objects = CommissioningScriptManager()
+
     name = CharField(max_length=255, null=False, editable=False, unique=True)
     content = BinaryField(null=False)

=== modified file 'src/metadataserver/tests/test_commissioningscript.py'
--- src/metadataserver/tests/test_commissioningscript.py	2012-11-23 11:40:16 +0000
+++ src/metadataserver/tests/test_commissioningscript.py	2012-11-29 20:52:44 +0000
@@ -12,13 +12,22 @@
 __metaclass__ = type
 __all__ = []
 
+from io import BytesIO
+import os.path
 from random import randint
+import tarfile
 
 from maasserver.testing.factory import factory
 from maasserver.testing.testcase import TestCase
 from maastesting.utils import sample_binary_data
 from metadataserver.fields import Bin
 from metadataserver.models import CommissioningScript
+from metadataserver.models.commissioningscript import ARCHIVE_PREFIX
+
+
+def open_tarfile(content):
+    """Open tar file from raw binary data."""
+    return tarfile.open(fileobj=BytesIO(content))
 
 
 def make_script_name(base_name=None, number=None):
@@ -31,6 +40,36 @@
         '%0.2d-%s' % (number, factory.make_name(base_name)))
 
 
+class TestCommissioningScriptManager(TestCase):
+
+    def test_get_archive_wraps_scripts_in_tar(self):
+        script = factory.make_commissioning_script()
+        archive = open_tarfile(CommissioningScript.objects.get_archive())
+        archived_script = archive.next()
+        self.assertTrue(archived_script.isfile())
+        self.assertEqual(
+            os.path.join(ARCHIVE_PREFIX, script.name),
+            archived_script.name)
+        self.assertEqual(
+            script.content,
+            archive.extractfile(archived_script).read())
+
+    def test_get_archive_wraps_all_scripts(self):
+        scripts = {factory.make_commissioning_script() for counter in range(3)}
+        archive = open_tarfile(CommissioningScript.objects.get_archive())
+        self.assertItemsEqual(
+            {os.path.join(ARCHIVE_PREFIX, script.name) for script in scripts},
+            archive.getnames())
+
+    def test_get_archive_supports_binary_scripts(self):
+        script = factory.make_commissioning_script(content=sample_binary_data)
+        archive = open_tarfile(CommissioningScript.objects.get_archive())
+        archived_script = archive.next()
+        self.assertEqual(
+            script.content,
+            archive.extractfile(archived_script).read())
+
+
 class TestCommissioningScript(TestCase):
 
     def test_scripts_may_be_binary(self):

_______________________________________________
Mailing list: https://launchpad.net/~launchpad-reviewers
Post to     : [email protected]
Unsubscribe : https://launchpad.net/~launchpad-reviewers
More help   : https://help.launchpad.net/ListHelp

Reply via email to