[lxc-devel] [pylxd/master] Allow multipart form uploads for images.
rockstar on Github
lxc-bot at linuxcontainers.org
Wed Nov 23 20:44:52 UTC 2016
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 654 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20161123/6b6b501d/attachment.bin>
-------------- next part --------------
From b558ef2ef02041ce6b46e0719bb9d5f97e2fd2e8 Mon Sep 17 00:00:00 2001
From: Paul Hummer <paul.hummer at canonical.com>
Date: Wed, 23 Nov 2016 13:41:51 -0700
Subject: [PATCH] Allow multipart form uploads for images.
In some cases, a user may want to upload a manifest with a raw image,
and pylxd previously didn't support that. This patch adds the needed
functionality.
As I did this, I found a bug in Image.create where fingerprint isn't
always reliably determined, so I have deprecated the ability to pass
a wait parameter to Image.create.
Fixes issue #172
---
pylxd/models/image.py | 56 +++++++++++++++++++++++++++++++++-------
pylxd/tests/models/test_image.py | 3 ++-
2 files changed, 49 insertions(+), 10 deletions(-)
diff --git a/pylxd/models/image.py b/pylxd/models/image.py
index 2293dd9..18caed4 100644
--- a/pylxd/models/image.py
+++ b/pylxd/models/image.py
@@ -12,8 +12,11 @@
# License for the specific language governing permissions and limitations
# under the License.
import contextlib
-import hashlib
import tempfile
+import uuid
+import warnings
+
+import six
from pylxd.models import _model as model
from pylxd.models.operation import Operation
@@ -82,19 +85,54 @@ def all(cls, client):
return images
@classmethod
- def create(cls, client, image_data, public=False, wait=False):
- """Create an image."""
- fingerprint = hashlib.sha256(image_data).hexdigest()
+ def create(
+ cls, client, image_data, metadata=None, public=False, wait=True):
+ """Create an image.
+
+ If metadata is provided, a multipart form data request is formed to
+ push metadata and image together in a single request. The metadata must
+ be a tar achive.
+
+ `wait` parameter is now ignored, as the image fingerprint cannot be
+ reliably determined consistently until after the image is indexed.
+ """
+
+ if wait is False:
+ warnings.warn(
+ 'Image.create wait parameter ignored and will be removed in '
+ '2.3', DeprecationWarning)
headers = {}
if public:
headers['X-LXD-Public'] = '1'
- response = client.api.images.post(
- data=image_data, headers=headers)
- if wait:
- Operation.wait_for_operation(client, response.json()['operation'])
- return cls(client, fingerprint=fingerprint)
+ if metadata is not None:
+ boundary = str(uuid.uuid1())
+
+ data = b''
+ for name, contents in (
+ ('metadata', metadata), ('rootfs', image_data)):
+ data += b'\r\n'.join([
+ six.b('--{}'.format(boundary)),
+ six.b(
+ 'Content-Disposition:form-data;'
+ 'name={};filename={}'.format(name, name)),
+ b'Content-Type: application/octet-stream',
+ b'',
+ contents,
+ b'',
+ ])
+ data += six.b('--{}--\r\n\r\n'.format(boundary))
+
+ headers['Content-Type'] = "multipart/form-data;boundary={}".format(
+ boundary)
+ else:
+ data = image_data
+
+ response = client.api.images.post(data=data, headers=headers)
+ operation = client.operations.wait_for_operation(
+ response.json()['operation'])
+ return cls(client, fingerprint=operation.metadata['fingerprint'])
@classmethod
def create_from_simplestreams(cls, client, server, alias,
diff --git a/pylxd/tests/models/test_image.py b/pylxd/tests/models/test_image.py
index 230b5da..9e2b39c 100644
--- a/pylxd/tests/models/test_image.py
+++ b/pylxd/tests/models/test_image.py
@@ -71,7 +71,8 @@ def test_all(self):
def test_create(self):
"""An image is created."""
fingerprint = hashlib.sha256(b'').hexdigest()
- a_image = models.Image.create(self.client, b'', public=True, wait=True)
+ a_image = models.Image.create(
+ self.client, b'', metadata=b'', public=True, wait=True)
self.assertIsInstance(a_image, models.Image)
self.assertEqual(fingerprint, a_image.fingerprint)
More information about the lxc-devel
mailing list