diff --git libcloud/compute/drivers/openstack.py libcloud/compute/drivers/openstack.py index ade1644..dc77021 100644 --- libcloud/compute/drivers/openstack.py +++ libcloud/compute/drivers/openstack.py @@ -30,6 +30,7 @@ import warnings from libcloud.utils.py3 import httplib from libcloud.utils.py3 import b from libcloud.utils.py3 import next +from libcloud.utils.py3 import urlparse import base64 @@ -934,8 +935,8 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver): optional_params['metadata'] = metadata resp = self._node_action(node, 'createImage', name=name, **optional_params) - # TODO: concevt location header into NodeImage object - return resp.status == httplib.ACCEPTED + image_id = self._extract_image_id_from_url(resp.headers['location']) + return self.ex_get_image(image_id) def ex_set_server_name(self, node, name): """ @@ -1065,3 +1066,8 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver): ) except KeyError: return(0.0) + + def _extract_image_id_from_url(self, location_header): + path = urlparse.urlparse(location_header).path + image_id = path.split('/')[-1] + return image_id diff --git test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json new file mode 100644 index 0000000..0e72070 --- /dev/null +++ test/compute/fixtures/openstack_v1.1/_images_4949f9ee_2421_4c81_8b49_13119446008b.json @@ -0,0 +1 @@ +{"image": {"status": "SAVING", "updated": "2012-01-05T19:42:20Z", "name": "new_image", "links": [{"href": "http://127.0.0.1/v1.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "rel": "self"}, {"href": "http://127.0.0.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "rel": "bookmark"}, {"href": "http://10.13.136.213:9292/68/images/4949f9ee-2421-4c81-8b49-13119446008b", "type": "application/vnd.openstack.image", "rel": "alternate"}], "created": "2012-01-05T19:42:20Z", "minDisk": 0, "server": {"id": "a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "links": [{"href": "http://127.0.0.1/v1.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "rel": "self"}, {"href": "http://127.0.0.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "rel": "bookmark"}]}, "progress": 25, "minRam": 0, "id": "4949f9ee-2421-4c81-8b49-13119446008b", "metadata": {"instance_uuid": "a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "image_state": "creating", "user_id": "reach6", "instance_ref": "http://127.0.0.1/v1.1/servers/a0fdd7b9-73e0-4e13-a01c-2bcb421be064", "image_type": "snapshot", "backup_type": null}}} diff --git test/compute/test_openstack.py test/compute/test_openstack.py index 55fc1ec..1d176e5 100644 --- test/compute/test_openstack.py +++ test/compute/test_openstack.py @@ -16,6 +16,11 @@ import sys import unittest import types +try: + import simplejson as json +except ImportError: + import json + from libcloud.utils.py3 import httplib from libcloud.utils.py3 import method_type from libcloud.utils.py3 import u @@ -608,8 +613,9 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin): self.fail('An error was raised: ' + repr(e)) def test_ex_save_image(self): - result = self.driver.ex_save_image(self.node, 'new_image') - self.assertTrue(result) + image = self.driver.ex_save_image(self.node, 'new_image') + self.assertEqual(image.name, 'new_image') + self.assertEqual(image.id, '4949f9ee-2421-4c81-8b49-13119446008b') def test_ex_set_server_name(self): old_node = Node( @@ -673,6 +679,14 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin): result = self.driver.ex_delete_image(image) self.assertTrue(result) + def test_extract_image_id_from_url(self): + url = 'http://127.0.0.1/v1.1/68/images/1d4a8ea9-aae7-4242-a42d-5ff4702f2f14' + url_two = 'http://127.0.0.1/v1.1/68/images/13' + image_id = self.driver._extract_image_id_from_url(url) + image_id_two = self.driver._extract_image_id_from_url(url_two) + self.assertEqual(image_id, '1d4a8ea9-aae7-4242-a42d-5ff4702f2f14') + self.assertEqual(image_id_two, '13') + class OpenStack_1_1_FactoryMethodTests(OpenStack_1_1_Tests): should_list_locations = False @@ -736,6 +750,10 @@ class OpenStack_1_1_MockHttp(MockHttpTestCase): def _v1_1_slug_servers_12064_action(self, method, url, body, headers): if method != "POST": self.fail('HTTP method other than POST to action URL') + if "createImage" in json.loads(body): + return (httplib.ACCEPTED, "", + {"location": "http://127.0.0.1/v1.1/68/images/4949f9ee-2421-4c81-8b49-13119446008b"}, + httplib.responses[httplib.ACCEPTED]) return (httplib.ACCEPTED, "", {}, httplib.responses[httplib.ACCEPTED]) @@ -790,6 +808,13 @@ class OpenStack_1_1_MockHttp(MockHttpTestCase): else: raise NotImplementedError() + def _v1_1_slug_images_4949f9ee_2421_4c81_8b49_13119446008b(self, method, url, body, headers): + if method == "GET": + body = self.fixtures.load('_images_4949f9ee_2421_4c81_8b49_13119446008b.json') + return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK]) + else: + raise NotImplementedError() + class OpenStack_1_1_Auth_2_0_MockHttp(OpenStack_1_1_MockHttp): fixtures = ComputeFileFixtures('openstack_v1.1') auth_fixtures = OpenStackFixtures()