diff --git a/etc/config.ini.sample b/etc/config.ini.sample index c27bb04e09..c0d9feab96 100644 --- a/etc/config.ini.sample +++ b/etc/config.ini.sample @@ -1,7 +1,7 @@ [environment] -kernel = include/sample_vm/natty-server-uec-amd64-vmlinuz-virtual -#initrd = include/sample_vm/natty-server-uec-amd64-initrd-virtual -image = include/sample_vm/natty-server-uec-amd64.img +aki_location = include/sample_vm/natty-server-cloudimg-amd64-vmlinuz-virtual +#ari_location = include/sample_vm/natty-server-cloudimg-amd64-loader +ami_location = include/sample_vm/natty-server-cloudimg-amd64.img [swift] auth_host = 10.0.0.100 diff --git a/include/sample_vm/README.txt b/include/sample_vm/README.txt index e8895ea9f1..51b609d0a0 100644 --- a/include/sample_vm/README.txt +++ b/include/sample_vm/README.txt @@ -2,5 +2,5 @@ You will need to download an image into this directory.. Will also need to update the tests to reference this new image. You could use e.g. the Ubuntu Natty cloud images (this matches the sample configuration): -$ wget http://cloud-images.ubuntu.com/releases/natty/release/ubuntu-11.04-server-uec-amd64.tar.gz -$ tar xvzf ubuntu-11.04-server-uec-amd64.tar.gz +$ wget http://cloud-images.ubuntu.com/releases/natty/release/ubuntu-11.04-server-cloudimg-amd64.tar.gz +$ tar xvzf ubuntu-11.04-server-cloudimg-amd64.tar.gz diff --git a/kong/tests/996_test_glance.py b/kong/tests/996_test_glance.py deleted file mode 100644 index 01cb110073..0000000000 --- a/kong/tests/996_test_glance.py +++ /dev/null @@ -1,206 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2011 OpenStack, LLC -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -"""Validate a working Glance deployment""" - -import httplib2 -import json -import os -from pprint import pprint - -from kong import tests - - -class TestGlanceAPI(tests.FunctionalTest): - def test_001_connect_to_glance_api(self): - """ - Verifies ability to connect to glance api, - expects glance to return an empty set - """ - if 'apiver' in self.glance: - path = "http://%s:%s/%s/images" % (self.glance['host'], - self.glance['port'], self.glance['apiver']) - else: - path = "http://%s:%s/images" % (self.glance['host'], - self.glance['port']) - http = httplib2.Http() - response, content = http.request(path, 'GET') - self.assertEqual(200, response.status) - data = json.loads(content) - self.assertTrue('images' in data) - test_001_connect_to_glance_api.tags = ['glance'] - - def test_002_upload_kernel_to_glance(self): - """ - Uploads a test kernal to glance api - """ - kernel = self.config['environment']['kernel'] - if 'apiver' in self.glance: - path = "http://%s:%s/%s/images" % (self.glance['host'], - self.glance['port'], self.glance['apiver']) - else: - path = "http://%s:%s/images" % (self.glance['host'], - self.glance['port']) - headers = {'x-image-meta-is-public': 'true', - 'x-image-meta-name': 'test-kernel', - 'x-image-meta-disk-format': 'aki', - 'x-image-meta-container-format': 'aki', - 'Content-Length': '%d' % os.path.getsize(kernel), - 'Content-Type': 'application/octet-stream'} - image_file = open(kernel, "rb") - http = httplib2.Http() - response, content = http.request(path, 'POST', - headers=headers, - body=image_file) - image_file.close() - self.assertEqual(201, response.status) - data = json.loads(content) - self.glance['kernel_id'] = data['image']['id'] - self.assertEqual(data['image']['name'], "test-kernel") - self.assertEqual(data['image']['checksum'], self._md5sum_file(kernel)) - test_002_upload_kernel_to_glance.tags = ['glance', 'nova'] - - def test_003_upload_initrd_to_glance(self): - """ - Uploads a test initrd to glance api - """ - if not 'initrd' in self.config['environment']: - self.glance['ramdisk_id'] = None - return - - initrd = self.config['environment']['initrd'] - - if 'apiver' in self.glance: - path = "http://%s:%s/%s/images" % (self.glance['host'], - self.glance['port'], self.glance['apiver']) - else: - path = "http://%s:%s/images" % (self.glance['host'], - self.glance['port']) - headers = {'x-image-meta-is-public': 'true', - 'x-image-meta-name': 'test-ramdisk', - 'x-image-meta-disk-format': 'ari', - 'x-image-meta-container-format': 'ari', - 'Content-Length': '%d' % os.path.getsize(initrd), - 'Content-Type': 'application/octet-stream'} - image_file = open(initrd, "rb") - http = httplib2.Http() - response, content = http.request(path, - 'POST', - headers=headers, - body=image_file) - image_file.close() - self.assertEqual(201, response.status) - data = json.loads(content) - self.glance['ramdisk_id'] = data['image']['id'] - self.assertEqual(data['image']['name'], "test-ramdisk") - self.assertEqual(data['image']['checksum'], self._md5sum_file(initrd)) - test_003_upload_initrd_to_glance.tags = ['glance', 'nova'] - - def test_004_upload_image_to_glance(self): - """ - Uploads a test image to glance api, and - links it to the initrd and kernel uploaded - earlier - """ - image = self.config['environment']['image'] - upload_data = "" - for chunk in self._read_in_chunks(image): - upload_data += chunk - if 'apiver' in self.glance: - path = "http://%s:%s/%s/images" % (self.glance['host'], - self.glance['port'], self.glance['apiver']) - else: - path = "http://%s:%s/images" % (self.glance['host'], - self.glance['port']) - headers = {'x-image-meta-is-public': 'true', - 'x-image-meta-name': 'test-image', - 'x-image-meta-disk-format': 'ami', - 'x-image-meta-container-format': 'ami', - 'x-image-meta-property-Kernel_id': '%s' % \ - self.glance['kernel_id'], - 'Content-Length': '%d' % os.path.getsize(image), - 'Content-Type': 'application/octet-stream'} - - if self.glance['ramdisk_id']: - ramdisk_id = '%s' % self.glance['ramdisk_id'] - headers['x-image-meta-property-Ramdisk_id'] = ramdisk_id - - http = httplib2.Http() - response, content = http.request(path, 'POST', - headers=headers, - body=upload_data) - self.assertEqual(201, response.status) - data = json.loads(content) - self.glance['image_id'] = data['image']['id'] - self.assertEqual(data['image']['name'], "test-image") - self.assertEqual(data['image']['checksum'], self._md5sum_file(image)) - test_004_upload_image_to_glance.tags = ['glance', 'nova'] - - def test_005_set_image_meta_property(self): - if 'apiver' in self.glance: - path = "http://%s:%s/%s/images/%s" % (self.glance['host'], - self.glance['port'], self.glance['apiver'], - self.glance['image_id']) - else: - path = "http://%s:%s/images/%s" % (self.glance['host'], - self.glance['port'], self.glance['image_id']) - headers = {'X-Image-Meta-Property-Distro': 'Ubuntu', - 'X-Image-Meta-Property-Arch': 'x86_64', - 'X-Image-Meta-Property-Kernel_id': '%s' % \ - self.glance['kernel_id']} - - if self.glance['ramdisk_id']: - ramdisk_id = '%s' % self.glance['ramdisk_id'] - headers['X-Image-Meta-Property-Ramdisk_id'] = ramdisk_id - - http = httplib2.Http() - response, content = http.request(path, 'PUT', headers=headers) - self.assertEqual(response.status, 200) - data = json.loads(content) - self.assertEqual(data['image']['properties']['arch'], "x86_64") - self.assertEqual(data['image']['properties']['distro'], "Ubuntu") - self.assertEqual(data['image']['properties']['kernel_id'], - str(self.glance['kernel_id'])) - if self.glance['ramdisk_id']: - self.assertEqual(data['image']['properties']['ramdisk_id'], - str(self.glance['ramdisk_id'])) - test_005_set_image_meta_property.tags = ['glance'] - - def test_006_list_image_metadata(self): - image = self.config['environment']['image'] - if 'apiver' in self.glance: - path = "http://%s:%s/%s/images/%s" % (self.glance['host'], - self.glance['port'], self.glance['apiver'], - self.glance['image_id']) - else: - path = "http://%s:%s/images/%s" % (self.glance['host'], - self.glance['port'], self.glance['image_id']) - http = httplib2.Http() - response, content = http.request(path, 'HEAD') - self.assertEqual(response.status, 200) - self.assertEqual(response['x-image-meta-name'], "test-image") - self.assertEqual(response['x-image-meta-checksum'], - self._md5sum_file(image)) - self.assertEqual(response['x-image-meta-container_format'], "ami") - self.assertEqual(response['x-image-meta-disk_format'], "ami") - self.assertEqual(response['x-image-meta-property-arch'], "x86_64") - self.assertEqual(response['x-image-meta-property-distro'], "Ubuntu") - self.assertEqual(response['x-image-meta-property-kernel_id'], - str(self.glance['kernel_id'])) - if self.glance['ramdisk_id']: - self.assertEqual(response['x-image-meta-property-ramdisk_id'], - str(self.glance['ramdisk_id'])) - test_006_list_image_metadata.tags = ['glance'] diff --git a/kong/tests/test_images.py b/kong/tests/test_images.py index d8a47210f1..1163723198 100644 --- a/kong/tests/test_images.py +++ b/kong/tests/test_images.py @@ -1,3 +1,4 @@ +import httplib2 import json import os import re @@ -6,10 +7,10 @@ from kong import openstack from kong import tests -class ImagesTest(tests.FunctionalTest): +class TestImagesThroughCompute(tests.FunctionalTest): def setUp(self): - super(ImagesTest, self).setUp() + super(TestImagesThroughCompute, self).setUp() self.os = openstack.Manager(self.nova) def _assert_image_links(self, image): @@ -82,3 +83,125 @@ class ImagesTest(tests.FunctionalTest): for image in resp_body['images']: self._assert_image_entity_detailed(image) test_detail.tags = ['nova', 'glance'] + + +class TestGlanceAPI(tests.FunctionalTest): + + def setUp(self): + super(TestGlanceAPI, self).setUp() + self.base_url = "http://%s:%s/%s/images" % (self.glance['host'], + self.glance['port'], + self.glance['apiver']) + + def test_upload_ami_style_image(self): + """Uploads a three-part ami-style image""" + aki_location = self.config['environment']['aki_location'] + headers = {'x-image-meta-is-public': 'true', + 'x-image-meta-name': 'test-kernel', + 'x-image-meta-disk-format': 'aki', + 'x-image-meta-container-format': 'aki', + 'Content-Length': '%d' % os.path.getsize(aki_location), + 'Content-Type': 'application/octet-stream'} + image_file = open(aki_location, "rb") + http = httplib2.Http() + response, content = http.request(self.base_url, 'POST', + headers=headers,body=image_file) + image_file.close() + self.assertEqual(201, response.status) + data = json.loads(content) + self.assertEqual(data['image']['name'], "test-kernel") + self.assertEqual(data['image']['checksum'], + self._md5sum_file(aki_location)) + kernel_id = data['image']['id'] + + ari_location = self.config['environment'].get('ari_location') + if ari_location: + headers = {'x-image-meta-is-public': 'true', + 'x-image-meta-name': 'test-ramdisk', + 'x-image-meta-disk-format': 'ari', + 'x-image-meta-container-format': 'ari', + 'Content-Length': '%d' % os.path.getsize(ari_location), + 'Content-Type': 'application/octet-stream'} + image_file = open(ari_location, "rb") + http = httplib2.Http() + response, content = http.request(self.base_url, 'POST', + headers=headers, body=image_file) + image_file.close() + self.assertEqual(201, response.status) + data = json.loads(content) + self.assertEqual(data['image']['name'], "test-ramdisk") + self.assertEqual(data['image']['checksum'], + self._md5sum_file(ari_location)) + ramdisk_id = data['image']['id'] + else: + ramdisk_id = None + + ami_location = self.config['environment']['ami_location'] + upload_data = "" + for chunk in self._read_in_chunks(ami_location): + upload_data += chunk + headers = {'x-image-meta-is-public': 'true', + 'x-image-meta-name': 'test-image', + 'x-image-meta-disk-format': 'ami', + 'x-image-meta-container-format': 'ami', + 'x-image-meta-property-kernel_id': kernel_id, + 'Content-Length': '%d' % os.path.getsize(ami_location), + 'Content-Type': 'application/octet-stream'} + + if ari_location: + headers['x-image-meta-property-ramdisk_id'] = ramdisk_id + + http = httplib2.Http() + response, content = http.request(self.base_url, 'POST', + headers=headers, body=upload_data) + self.assertEqual(201, response.status) + data = json.loads(content) + self.assertEqual(data['image']['name'], "test-image") + self.assertEqual(data['image']['checksum'], + self._md5sum_file(ami_location)) + machine_id = data['image']['id'] + + # now ensure we can modify the image properties + headers = {'X-Image-Meta-Property-distro': 'Ubuntu', + 'X-Image-Meta-Property-arch': 'x86_64', + 'X-Image-Meta-Property-kernel_id': kernel_id} + if ari_location: + headers['X-Image-Meta-Property-ramdisk_id'] = ramdisk_id + + http = httplib2.Http() + url = '%s/%s' % (self.base_url, machine_id) + response, content = http.request(url, 'PUT', headers=headers) + self.assertEqual(response.status, 200) + data = json.loads(content) + properties = data['image']['properties'] + self.assertEqual(properties['arch'], "x86_64") + self.assertEqual(properties['distro'], "Ubuntu") + self.assertEqual(properties['kernel_id'], kernel_id) + if ari_location: + self.assertEqual(properties['ramdisk_id'], ramdisk_id) + + # list the metadata to ensure the new values stuck + http = httplib2.Http() + response, content = http.request(url, 'HEAD') + self.assertEqual(response.status, 200) + self.assertEqual(response['x-image-meta-name'], "test-image") + self.assertEqual(response['x-image-meta-checksum'], + self._md5sum_file(ami_location)) + self.assertEqual(response['x-image-meta-container_format'], "ami") + self.assertEqual(response['x-image-meta-disk_format'], "ami") + self.assertEqual(response['x-image-meta-property-arch'], "x86_64") + self.assertEqual(response['x-image-meta-property-distro'], "Ubuntu") + self.assertEqual(response['x-image-meta-property-kernel_id'], + kernel_id) + if ari_location: + self.assertEqual(response['x-image-meta-property-ramdisk_id'], + ramdisk_id) + + # delete images for which we have non-None ids + delete_ids = filter(lambda x: x, (kernel_id, ramdisk_id, machine_id)) + for image_id in delete_ids: + http = httplib2.Http() + url = '%s/%s' % (self.base_url, image_id) + response, content = http.request(url, 'DELETE') + + test_upload_ami_style_image.tags = ['glance']