summaryrefslogtreecommitdiffstats
path: root/nova
diff options
context:
space:
mode:
authorVishvananda Ishaya <vishvananda@gmail.com>2011-03-07 01:25:01 +0000
committerVishvananda Ishaya <vishvananda@gmail.com>2011-03-07 01:25:01 +0000
commita5bee00af4d6ec3eed6ed0abd866948f4510f041 (patch)
tree2c924050978a0ae63ed2df5dd6bf1d279a7e9b27 /nova
parentf3c1c99ca0f6f3164430b33f46772ef8bdc87b70 (diff)
downloadnova-a5bee00af4d6ec3eed6ed0abd866948f4510f041.tar.gz
nova-a5bee00af4d6ec3eed6ed0abd866948f4510f041.tar.xz
nova-a5bee00af4d6ec3eed6ed0abd866948f4510f041.zip
make compute get the new images properly, fix a bunch of tests, and provide conversion commands
Diffstat (limited to 'nova')
-rw-r--r--nova/api/ec2/cloud.py74
-rw-r--r--nova/api/ec2/ec2utils.py6
-rw-r--r--nova/compute/api.py4
-rw-r--r--nova/image/glance.py35
-rw-r--r--nova/image/local.py52
-rw-r--r--nova/image/s3.py33
-rw-r--r--nova/image/service.py18
-rw-r--r--nova/tests/test_cloud.py16
-rw-r--r--nova/tests/test_compute.py12
-rw-r--r--nova/tests/test_console.py2
-rw-r--r--nova/tests/test_quota.py32
-rw-r--r--nova/tests/test_scheduler.py4
-rw-r--r--nova/tests/test_volume.py2
-rw-r--r--nova/virt/images.py25
-rw-r--r--nova/virt/libvirt_conn.py8
15 files changed, 216 insertions, 107 deletions
diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py
index 3ea3fa07e..496e944fe 100644
--- a/nova/api/ec2/cloud.py
+++ b/nova/api/ec2/cloud.py
@@ -146,10 +146,13 @@ class CloudController(object):
floating_ip = db.instance_get_floating_address(ctxt,
instance_ref['id'])
ec2_id = ec2utils.id_to_ec2_id(instance_ref['id'])
+ image_ec2_id = self._image_ec2_id(instance_ref['image_id'], 'machine')
+ k_ec2_id = self._image_ec2_id(instance_ref['kernel_id'], 'kernel')
+ r_ec2_id = self._image_ec2_id(instance_ref['ramdisk_id'], 'ramdisk')
data = {
'user-data': base64.b64decode(instance_ref['user_data']),
'meta-data': {
- 'ami-id': instance_ref['image_id'],
+ 'ami-id': image_ec2_id,
'ami-launch-index': instance_ref['launch_index'],
'ami-manifest-path': 'FIXME',
'block-device-mapping': {
@@ -164,12 +167,12 @@ class CloudController(object):
'instance-type': instance_ref['instance_type'],
'local-hostname': hostname,
'local-ipv4': address,
- 'kernel-id': instance_ref['kernel_id'],
+ 'kernel-id': k_ec2_id,
+ 'ramdisk-id': r_ec2_id,
'placement': {'availability-zone': availability_zone},
'public-hostname': hostname,
'public-ipv4': floating_ip or '',
'public-keys': keys,
- 'ramdisk-id': instance_ref['ramdisk_id'],
'reservation-id': instance_ref['reservation_id'],
'security-groups': '',
'mpi': mpi}}
@@ -679,7 +682,7 @@ class CloudController(object):
instance_id = instance['id']
ec2_id = ec2utils.id_to_ec2_id(instance_id)
i['instanceId'] = ec2_id
- i['imageId'] = instance['image_id']
+ i['imageId'] = self._image_ec2_id(instance['image_id'])
i['instanceState'] = {
'code': instance['state'],
'name': instance['state_description']}
@@ -782,13 +785,15 @@ class CloudController(object):
def run_instances(self, context, **kwargs):
max_count = int(kwargs.get('max_count', 1))
if kwargs.get('kernel_id'):
- kwargs['kernel_id'] = ec2utils.ec2_id_to_id(kwargs['kernel_id'])
+ kernel = self._get_image(context, kwargs['kernel_id'])
+ kwargs['kernel_id'] = kernel['id']
if kwargs.get('ramdisk_id'):
- kwargs['ramdisk_id'] = ec2utils.ec2_id_to_id(kwargs['ramdisk_id'])
+ ramdisk = self._get_image(context, kwargs['ramdisk_id'])
+ kwargs['ramdisk_id'] = ramdisk['id']
instances = self.compute_api.create(context,
instance_type=instance_types.get_by_type(
kwargs.get('instance_type', None)),
- image_id=ec2utils.ec2_id_to_id(kwargs['image_id']),
+ image_id=self._get_image(context, kwargs['image_id'])['id'],
min_count=int(kwargs.get('min_count', max_count)),
max_count=max_count,
kernel_id=kwargs.get('kernel_id'),
@@ -847,17 +852,34 @@ class CloudController(object):
'kernel': 'aki',
'ramdisk': 'ari'}
- def _image_ec2_id(self, image_id, image_type):
+ def _image_ec2_id(self, image_id, image_type='machine'):
prefix = self._type_prefix_map[image_type]
template = prefix + '-%08x'
return ec2utils.id_to_ec2_id(int(image_id), template=template)
+ def _get_image(self, context, ec2_id):
+ try:
+ internal_id = ec2utils.ec2_id_to_id(ec2_id)
+ return self.image_service.show(context, internal_id)
+ except exception.NotFound:
+ return self.image_service.show_by_name(context, ec2_id)
+
+
def _format_image(self, image):
"""Convert from format defined by BaseImageService to S3 format."""
i = {}
- i['imageId'] = self._image_ec2_id(image.get('id'), image.get('type'))
- i['kernelId'] = image['properties'].get('kernel_id')
- i['ramdiskId'] = image['properties'].get('ramdisk_id')
+ ec2_id = self._image_ec2_id(image.get('id'), image.get('type'))
+ name = image.get('name')
+ if name:
+ i['imageId'] = "%s (%s)" % (ec2_id, name)
+ else:
+ i['imageId'] = ec2_id
+ kernel_id = image['properties'].get('kernel_id')
+ if kernel_id:
+ i['kernelId'] = self._image_ec2_id(kernel_id, 'kernel')
+ ramdisk_id = image['properties'].get('ramdisk_id')
+ if ramdisk_id:
+ i['ramdiskId'] = self._image_ec2_id(ramdisk_id, 'ramdisk')
i['imageOwnerId'] = image['properties'].get('owner_id')
i['imageLocation'] = image['properties'].get('image_location')
i['imageState'] = image['properties'].get('image_state')
@@ -872,8 +894,7 @@ class CloudController(object):
images = []
for ec2_id in image_id:
try:
- internal_id = ec2utils.ec2_id_to_id(ec2_id)
- image = self.image_service.show(context, internal_id)
+ image = self._get_image(context, ec2_id)
except exception.NotFound:
raise exception.NotFound(_('Image %s not found') %
ec2_id)
@@ -885,16 +906,17 @@ class CloudController(object):
def deregister_image(self, context, image_id, **kwargs):
LOG.audit(_("De-registering image %s"), image_id, context=context)
- internal_id = ec2utils.ec2_id_to_id(image_id)
+ image = self._get_image(context, image_id)
+ internal_id = image['id']
self.image_service.delete(context, internal_id)
return {'imageId': image_id}
def register_image(self, context, image_location=None, **kwargs):
if image_location is None and 'name' in kwargs:
image_location = kwargs['name']
- metadata = {"image_location": image_location}
+ metadata = {'properties': {'image_location': image_location}}
image = self.image_service.create(context, metadata)
- image_id = self._image_ec2_id(image['id'], image['type'])
+ image_id = self._image_ec2_id(image['id'], image['type'])
msg = _("Registered image %(image_location)s with"
" id %(image_id)s") % locals()
LOG.audit(msg, context=context)
@@ -905,13 +927,11 @@ class CloudController(object):
raise exception.ApiError(_('attribute not supported: %s')
% attribute)
try:
- internal_id = ec2utils.ec2_id_to_id(image_id)
- image = self._format_image(self.image_service.show(context,
- internal_id))
- except (IndexError, exception.NotFound):
+ image = self._get_image(context, image_id)
+ except exception.NotFound:
raise exception.NotFound(_('Image %s not found') % image_id)
- result = {'image_id': image_id, 'launchPermission': []}
- if image['isPublic']:
+ result = {'imageId': image_id, 'launchPermission': []}
+ if image['properties']['is_public']:
result['launchPermission'].append({'group': 'all'})
return result
@@ -930,13 +950,13 @@ class CloudController(object):
LOG.audit(_("Updating image %s publicity"), image_id, context=context)
try:
- internal_id = ec2utils.ec2_id_to_id(image_id)
- metadata = self.image_service.show(context, internal_id)
+ image = self._get_image(context, image_id)
except exception.NotFound:
raise exception.NotFound(_('Image %s not found') % image_id)
- del(metadata['id'])
- metadata['properties']['is_public'] = (operation_type == 'add')
- return self.image_service.update(context, internal_id, metadata)
+ internal_id = image['id']
+ del(image['id'])
+ image['properties']['is_public'] = (operation_type == 'add')
+ return self.image_service.update(context, internal_id, image)
def update_image(self, context, image_id, **kwargs):
internal_id = ec2utils.ec2_id_to_id(image_id)
diff --git a/nova/api/ec2/ec2utils.py b/nova/api/ec2/ec2utils.py
index 0ea22c0e6..e4df80cf8 100644
--- a/nova/api/ec2/ec2utils.py
+++ b/nova/api/ec2/ec2utils.py
@@ -16,10 +16,14 @@
# License for the specific language governing permissions and limitations
# under the License.
+from nova import exception
def ec2_id_to_id(ec2_id):
"""Convert an ec2 ID (i-[base 16 number]) to an instance id (int)"""
- return int(ec2_id.split('-')[-1], 16)
+ try:
+ return int(ec2_id.split('-')[-1], 16)
+ except ValueError:
+ raise exception.NotFound(_("Id %s Not Found") % ec2_id)
def id_to_ec2_id(instance_id, template='i-%08x'):
diff --git a/nova/compute/api.py b/nova/compute/api.py
index 35a7d7bc0..58118121a 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -126,9 +126,9 @@ class API(base.Base):
image = self.image_service.show(context, image_id)
if kernel_id is None:
- kernel_id = image.get('kernel_id', None)
+ kernel_id = image['properties'].get('kernel_id', None)
if ramdisk_id is None:
- ramdisk_id = image.get('ramdisk_id', None)
+ ramdisk_id = image['properties'].get('ramdisk_id', None)
# FIXME(sirp): is there a way we can remove null_kernel?
# No kernel and ramdisk for raw images
if kernel_id == str(FLAGS.null_kernel):
diff --git a/nova/image/glance.py b/nova/image/glance.py
index 7db94c0d4..fb383f5e6 100644
--- a/nova/image/glance.py
+++ b/nova/image/glance.py
@@ -17,9 +17,6 @@
"""Implementation of an image service that uses Glance as the backend"""
from __future__ import absolute_import
-import httplib
-import json
-import urlparse
from glance.common import exception as glance_exception
@@ -55,16 +52,44 @@ class GlanceImageService(service.BaseImageService):
"""
return self.client.get_images_detailed()
- def show(self, context, id):
+ def show(self, context, image_id):
"""
Returns a dict containing image data for the given opaque image id.
"""
try:
- image = self.client.get_image_meta(id)
+ image = self.client.get_image_meta(image_id)
except glance_exception.NotFound:
raise exception.NotFound
return image
+ def show_by_name(self, context, name):
+ """
+ Returns a dict containing image data for the given name.
+ """
+ # TODO(vish): replace this with more efficient call when glance
+ # supports it.
+ images = self.detail(context)
+ image = None
+ for cantidate in images:
+ if name == cantidate.get('name'):
+ image = cantidate
+ break
+ if image == None:
+ raise exception.NotFound
+ return image
+
+ def get(self, context, image_id, data):
+ """
+ Calls out to Glance for metadata and data and writes data.
+ """
+ try:
+ metadata, image_chunks = self.client.get_image(image_id)
+ except glance_exception.NotFound:
+ raise exception.NotFound
+ for chunk in image_chunks:
+ data.write(chunk)
+ return metadata
+
def create(self, context, metadata, data=None):
"""
Store the image data and return the new image id.
diff --git a/nova/image/local.py b/nova/image/local.py
index 6fa648b6b..c4ac3baaa 100644
--- a/nova/image/local.py
+++ b/nova/image/local.py
@@ -42,13 +42,12 @@ class LocalImageService(service.BaseImageService):
def _path_to(self, image_id, fname='info.json'):
if fname:
- return os.path.join(self._path, str(image_id), fname)
- return os.path.join(self._path, str(image_id))
+ return os.path.join(self._path, '%08x' % int(image_id), fname)
+ return os.path.join(self._path, '%08x' % int(image_id))
def _ids(self):
"""The list of all image ids."""
- return [int(i) for i in os.listdir(self._path)
- if unicode(i).isnumeric()]
+ return [int(i, 16) for i in os.listdir(self._path)]
def index(self, context):
return [dict(image_id=i['id'], name=i.get('name'))
@@ -68,27 +67,56 @@ class LocalImageService(service.BaseImageService):
try:
with open(self._path_to(image_id)) as metadata_file:
return json.load(metadata_file)
- except IOError:
+ except (IOError, ValueError):
raise exception.NotFound
+ def show_by_name(self, context, name):
+ """Returns a dict containing image data for the given name."""
+ # NOTE(vish): Not very efficient, but the local image service
+ # is for testing so it should be fine.
+ images = self.detail(context)
+ image = None
+ for cantidate in images:
+ if name == cantidate.get('name'):
+ image = cantidate
+ break
+ if image == None:
+ raise exception.NotFound
+ return image
+
+ def get(self, context, image_id, data):
+ """Get image and metadata."""
+ try:
+ with open(self._path_to(image_id)) as metadata_file:
+ metadata = json.load(metadata_file)
+ with open(self._path_to(image_id, 'image')) as image_file:
+ shutil.copyfileobj(image_file, data)
+ except (IOError, ValueError):
+ raise exception.NotFound
+ return metadata
+
def create(self, context, metadata, data=None):
- """Store the image data and return the new image id."""
+ """Store the image data and return the new image."""
image_id = random.randint(0, 2 ** 31 - 1)
image_path = self._path_to(image_id, None)
if not os.path.exists(image_path):
os.mkdir(image_path)
- return self.update(context, image_id, metadata, data)
+ return self.update(context, image_id, metadata, data)
def update(self, context, image_id, metadata, data=None):
"""Replace the contents of the given image with the new data."""
metadata['id'] = image_id
try:
- with open(self._path_to(image_id), 'w') as metadata_file:
- json.dump(metadata, metadata_file)
if data:
- with open(self._path_to(image_id, 'image'), 'w') as image_file:
+ location = self._path_to(image_id, 'image')
+ with open(location, 'w') as image_file:
shutil.copyfileobj(data, image_file)
- except IOError:
+ # NOTE(vish): update metadata similarly to glance
+ metadata['status'] = 'active'
+ metadata['location'] = location
+ with open(self._path_to(image_id), 'w') as metadata_file:
+ json.dump(metadata, metadata_file)
+ except (IOError, ValueError):
raise exception.NotFound
return metadata
@@ -99,7 +127,7 @@ class LocalImageService(service.BaseImageService):
"""
try:
shutil.rmtree(self._path_to(image_id, None))
- except IOError:
+ except (IOError, ValueError):
raise exception.NotFound
def delete_all(self):
diff --git a/nova/image/s3.py b/nova/image/s3.py
index c7446f4b0..ab6eea8cf 100644
--- a/nova/image/s3.py
+++ b/nova/image/s3.py
@@ -36,6 +36,7 @@ from nova import flags
from nova import utils
from nova.auth import manager
from nova.image import service
+from nova.api.ec2 import ec2utils
FLAGS = flags.FLAGS
@@ -51,7 +52,7 @@ class S3ImageService(service.BaseImageService):
self.service.__init__(*args, **kwargs)
def create(self, context, metadata, data=None):
- """metadata should contain image_location"""
+ """metadata['properties'] should contain image_location"""
image = self._s3_create(context, metadata)
return image
@@ -97,6 +98,12 @@ class S3ImageService(service.BaseImageService):
raise exception.NotFound
return image
+ def show_by_name(self, context, name):
+ image = self.service.show_by_name(context, name)
+ if not self._is_visible(context, image):
+ raise exception.NotFound
+ return image
+
@staticmethod
def _conn(context):
# TODO(vish): is there a better way to get creds to sign
@@ -119,10 +126,12 @@ class S3ImageService(service.BaseImageService):
key.get_contents_to_filename(local_filename)
return local_filename
- def _s3_create(self, context, properties):
+ def _s3_create(self, context, metadata):
+ """Gets a manifext from s3 and makes an image"""
+
image_path = tempfile.mkdtemp(dir=FLAGS.image_decryption_dir)
- image_location = properties['image_location']
+ image_location = metadata['properties']['image_location']
bucket_name = image_location.split("/")[0]
manifest_path = image_location[len(bucket_name) + 1:]
bucket = self._conn(context).get_bucket(bucket_name)
@@ -153,25 +162,27 @@ class S3ImageService(service.BaseImageService):
except:
arch = 'x86_64'
- properties.update({'owner_id': context.project_id,
- 'architecture': arch})
+ properties = metadata['properties']
+ properties['owner_id'] = context.project_id
+ properties['architecture'] = arch
if kernel_id:
- properties['kernel_id'] = kernel_id
+ properties['kernel_id'] = ec2utils.ec2_id_to_id(kernel_id)
if ramdisk_id:
- properties['ramdisk_id'] = ramdisk_id
+ properties['ramdisk_id'] = ec2utils.ec2_id_to_id(ramdisk_id)
properties['is_public'] = False
- metadata = {'type': image_type,
- 'status': 'queued',
- 'is_public': True,
- 'properties': properties}
+ metadata.update({'type': image_type,
+ 'status': 'queued',
+ 'is_public': True,
+ 'properties': properties})
metadata['properties']['image_state'] = 'pending'
image = self.service.create(context, metadata)
image_id = image['id']
def delayed_create():
+ """This handles the fetching and decrypting of the part files."""
parts = []
for fn_element in manifest.find("image").getiterator("filename"):
part = self._download_file(bucket, fn_element.text, image_path)
diff --git a/nova/image/service.py b/nova/image/service.py
index e429955f4..c09052cab 100644
--- a/nova/image/service.py
+++ b/nova/image/service.py
@@ -56,9 +56,9 @@ class BaseImageService(object):
"""
raise NotImplementedError
- def show(self, context, id):
+ def show(self, context, image_id):
"""
- Returns a dict containing image data for the given opaque image id.
+ Returns a dict containing image metadata for the given opaque image id.
:retval a mapping with the following signature:
@@ -76,9 +76,19 @@ class BaseImageService(object):
"""
raise NotImplementedError
+ def get(self, context, data):
+ """
+ Returns a dict containing image metadata and writes image data to data.
+
+ :param data: a file-like object to hold binary image data
+
+ :raises NotFound if the image does not exist
+ """
+ raise NotImplementedError
+
def create(self, context, metadata, data=None):
"""
- Store the image data and return the new image id.
+ Store the image metadata and data and return the new image id.
:raises AlreadyExists if the image already exist.
@@ -86,7 +96,7 @@ class BaseImageService(object):
raise NotImplementedError
def update(self, context, image_id, metadata, data=None):
- """Replace the contents of the given image with the new data.
+ """Update the given image with the new metadata and data.
:raises NotFound if the image does not exist.
diff --git a/nova/tests/test_cloud.py b/nova/tests/test_cloud.py
index 7d7b91658..8d2cd9573 100644
--- a/nova/tests/test_cloud.py
+++ b/nova/tests/test_cloud.py
@@ -78,10 +78,11 @@ class CloudTestCase(test.TestCase):
project=self.project)
host = self.network.get_network_host(self.context.elevated())
- def fake_image_show(meh, context, id):
- return dict(kernelId=1, ramdiskId=1)
+ def fake_show(meh, context, id):
+ return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}}
- self.stubs.Set(local.LocalImageService, 'show', fake_image_show)
+ self.stubs.Set(local.LocalImageService, 'show', fake_show)
+ self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
def tearDown(self):
network_ref = db.project_get_network(self.context,
@@ -195,8 +196,10 @@ class CloudTestCase(test.TestCase):
def test_describe_instances(self):
"""Makes sure describe_instances works and filters results."""
inst1 = db.instance_create(self.context, {'reservation_id': 'a',
+ 'image_id': 1,
'host': 'host1'})
inst2 = db.instance_create(self.context, {'reservation_id': 'a',
+ 'image_id': 1,
'host': 'host2'})
comp1 = db.service_create(self.context, {'host': 'host1',
'availability_zone': 'zone1',
@@ -222,11 +225,9 @@ class CloudTestCase(test.TestCase):
db.service_destroy(self.context, comp2['id'])
def test_console_output(self):
- image_id = FLAGS.default_image
- print image_id
instance_type = FLAGS.default_instance_type
max_count = 1
- kwargs = {'image_id': image_id,
+ kwargs = {'image_id': 'ami-1',
'instance_type': instance_type,
'max_count': max_count}
rv = self.cloud.run_instances(self.context, **kwargs)
@@ -242,8 +243,7 @@ class CloudTestCase(test.TestCase):
greenthread.sleep(0.3)
def test_ajax_console(self):
- image_id = FLAGS.default_image
- kwargs = {'image_id': image_id}
+ kwargs = {'image_id': 'ami-1'}
rv = self.cloud.run_instances(self.context, **kwargs)
instance_id = rv['instancesSet'][0]['instanceId']
greenthread.sleep(0.3)
diff --git a/nova/tests/test_compute.py b/nova/tests/test_compute.py
index 1f49baaf6..8c18fafc6 100644
--- a/nova/tests/test_compute.py
+++ b/nova/tests/test_compute.py
@@ -47,16 +47,16 @@ class ComputeTestCase(test.TestCase):
network_manager='nova.network.manager.FlatManager')
self.compute = utils.import_object(FLAGS.compute_manager)
self.compute_api = compute.API()
-
- def fake_image_show(meh, context, id):
- return dict(kernelId=1, ramdiskId=1)
-
- self.stubs.Set(local.LocalImageService, 'show', fake_image_show)
self.manager = manager.AuthManager()
self.user = self.manager.create_user('fake', 'fake', 'fake')
self.project = self.manager.create_project('fake', 'fake', 'fake')
self.context = context.RequestContext('fake', 'fake', False)
+ def fake_show(meh, context, id):
+ return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}}
+
+ self.stubs.Set(local.LocalImageService, 'show', fake_show)
+
def tearDown(self):
self.manager.delete_user(self.user)
self.manager.delete_project(self.project)
@@ -65,7 +65,7 @@ class ComputeTestCase(test.TestCase):
def _create_instance(self):
"""Create a test instance"""
inst = {}
- inst['image_id'] = 'ami-test'
+ inst['image_id'] = 1
inst['reservation_id'] = 'r-fakeres'
inst['launch_time'] = '10'
inst['user_id'] = self.user.id
diff --git a/nova/tests/test_console.py b/nova/tests/test_console.py
index 49ff24413..d47c70d88 100644
--- a/nova/tests/test_console.py
+++ b/nova/tests/test_console.py
@@ -57,7 +57,7 @@ class ConsoleTestCase(test.TestCase):
inst = {}
#inst['host'] = self.host
#inst['name'] = 'instance-1234'
- inst['image_id'] = 'ami-test'
+ inst['image_id'] = 1
inst['reservation_id'] = 'r-fakeres'
inst['launch_time'] = '10'
inst['user_id'] = self.user.id
diff --git a/nova/tests/test_quota.py b/nova/tests/test_quota.py
index ca8abdb36..45b544753 100644
--- a/nova/tests/test_quota.py
+++ b/nova/tests/test_quota.py
@@ -20,11 +20,12 @@ from nova import compute
from nova import context
from nova import db
from nova import flags
+from nova import network
from nova import quota
from nova import test
from nova import utils
+from nova import volume
from nova.auth import manager
-from nova.api.ec2 import cloud
from nova.compute import instance_types
@@ -41,7 +42,6 @@ class QuotaTestCase(test.TestCase):
quota_gigabytes=20,
quota_floating_ips=1)
- self.cloud = cloud.CloudController()
self.manager = manager.AuthManager()
self.user = self.manager.create_user('admin', 'admin', 'admin', True)
self.project = self.manager.create_project('admin', 'admin', 'admin')
@@ -57,7 +57,7 @@ class QuotaTestCase(test.TestCase):
def _create_instance(self, cores=2):
"""Create a test instance"""
inst = {}
- inst['image_id'] = 'ami-1'
+ inst['image_id'] = 1
inst['reservation_id'] = 'r-fakeres'
inst['user_id'] = self.user.id
inst['project_id'] = self.project.id
@@ -118,12 +118,12 @@ class QuotaTestCase(test.TestCase):
for i in range(FLAGS.quota_instances):
instance_id = self._create_instance()
instance_ids.append(instance_id)
- self.assertRaises(quota.QuotaError, self.cloud.run_instances,
+ self.assertRaises(quota.QuotaError, compute.API().create,
self.context,
min_count=1,
max_count=1,
instance_type='m1.small',
- image_id='ami-1')
+ image_id=1)
for instance_id in instance_ids:
db.instance_destroy(self.context, instance_id)
@@ -131,12 +131,12 @@ class QuotaTestCase(test.TestCase):
instance_ids = []
instance_id = self._create_instance(cores=4)
instance_ids.append(instance_id)
- self.assertRaises(quota.QuotaError, self.cloud.run_instances,
+ self.assertRaises(quota.QuotaError, compute.API().create,
self.context,
min_count=1,
max_count=1,
instance_type='m1.small',
- image_id='ami-1')
+ image_id=1)
for instance_id in instance_ids:
db.instance_destroy(self.context, instance_id)
@@ -145,9 +145,12 @@ class QuotaTestCase(test.TestCase):
for i in range(FLAGS.quota_volumes):
volume_id = self._create_volume()
volume_ids.append(volume_id)
- self.assertRaises(quota.QuotaError, self.cloud.create_volume,
- self.context,
- size=10)
+ self.assertRaises(quota.QuotaError,
+ volume.API().create,
+ self.context,
+ size=10,
+ name='',
+ description='')
for volume_id in volume_ids:
db.volume_destroy(self.context, volume_id)
@@ -156,9 +159,11 @@ class QuotaTestCase(test.TestCase):
volume_id = self._create_volume(size=20)
volume_ids.append(volume_id)
self.assertRaises(quota.QuotaError,
- self.cloud.create_volume,
+ volume.API().create,
self.context,
- size=10)
+ size=10,
+ name='',
+ description='')
for volume_id in volume_ids:
db.volume_destroy(self.context, volume_id)
@@ -172,7 +177,8 @@ class QuotaTestCase(test.TestCase):
# make an rpc.call, the test just finishes with OK. It
# appears to be something in the magic inline callbacks
# that is breaking.
- self.assertRaises(quota.QuotaError, self.cloud.allocate_address,
+ self.assertRaises(quota.QuotaError,
+ network.API().allocate_floating_ip,
self.context)
db.floating_ip_destroy(context.get_admin_context(), address)
diff --git a/nova/tests/test_scheduler.py b/nova/tests/test_scheduler.py
index b6888c4d2..bb279ac4b 100644
--- a/nova/tests/test_scheduler.py
+++ b/nova/tests/test_scheduler.py
@@ -155,7 +155,7 @@ class SimpleDriverTestCase(test.TestCase):
def _create_instance(self, **kwargs):
"""Create a test instance"""
inst = {}
- inst['image_id'] = 'ami-test'
+ inst['image_id'] = 1
inst['reservation_id'] = 'r-fakeres'
inst['user_id'] = self.user.id
inst['project_id'] = self.project.id
@@ -169,8 +169,6 @@ class SimpleDriverTestCase(test.TestCase):
def _create_volume(self):
"""Create a test volume"""
vol = {}
- vol['image_id'] = 'ami-test'
- vol['reservation_id'] = 'r-fakeres'
vol['size'] = 1
vol['availability_zone'] = 'test'
return db.volume_create(self.context, vol)['id']
diff --git a/nova/tests/test_volume.py b/nova/tests/test_volume.py
index b40ca004b..f698c85b5 100644
--- a/nova/tests/test_volume.py
+++ b/nova/tests/test_volume.py
@@ -99,7 +99,7 @@ class VolumeTestCase(test.TestCase):
def test_run_attach_detach_volume(self):
"""Make sure volume can be attached and detached from instance."""
inst = {}
- inst['image_id'] = 'ami-test'
+ inst['image_id'] = 1
inst['reservation_id'] = 'r-fakeres'
inst['launch_time'] = '10'
inst['user_id'] = 'fake'
diff --git a/nova/virt/images.py b/nova/virt/images.py
index 7a6fef330..06b3a8ecd 100644
--- a/nova/virt/images.py
+++ b/nova/virt/images.py
@@ -28,29 +28,32 @@ import time
import urllib2
import urlparse
+from nova import context
from nova import flags
from nova import log as logging
from nova import utils
from nova.auth import manager
from nova.auth import signer
-from nova.objectstore import image
FLAGS = flags.FLAGS
-flags.DEFINE_bool('use_s3', True,
- 'whether to get images from s3 or use local copy')
-
LOG = logging.getLogger('nova.virt.images')
-def fetch(image, path, user, project):
- if FLAGS.use_s3:
- f = _fetch_s3_image
- else:
- f = _fetch_local_image
- return f(image, path, user, project)
+def fetch(image_id, path, _user, _project):
+ # TODO(vish): Improve context handling and add owner and auth data
+ # when it is added to glance. Right now there is no
+ # auth checking in glance, so we assume that access was
+ # checked before we got here.
+ image_service = utils.import_object(FLAGS.image_service)
+ with open(path, "wb") as image_file:
+ elevated = context.get_admin_context()
+ metadata = image_service.get(elevated, image_id, image_file)
+ return metadata
+# NOTE(vish): The methods below should be unnecessary, but I'm leaving
+# them in case the glance client does not work on windows.
def _fetch_image_no_curl(url, path, headers):
request = urllib2.Request(url)
for (k, v) in headers.iteritems():
@@ -110,6 +113,8 @@ def _image_path(path):
return os.path.join(FLAGS.images_path, path)
+# TODO(vish): xenapi should use the glance client code directly instead
+# of retrieving the image using this method.
def image_url(image):
if FLAGS.image_service == "nova.image.glance.GlanceImageService":
return "http://%s:%s/images/%s" % (FLAGS.glance_host,
diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py
index 9f7315c17..02a8208d5 100644
--- a/nova/virt/libvirt_conn.py
+++ b/nova/virt/libvirt_conn.py
@@ -579,21 +579,23 @@ class LibvirtConnection(object):
'ramdisk_id': inst['ramdisk_id']}
if disk_images['kernel_id']:
+ fname = '%08x' % int(disk_images['kernel_id'])
self._cache_image(fn=self._fetch_image,
target=basepath('kernel'),
- fname=disk_images['kernel_id'],
+ fname=fname,
image_id=disk_images['kernel_id'],
user=user,
project=project)
if disk_images['ramdisk_id']:
+ fname = '%08x' % int(disk_images['ramdisk_id'])
self._cache_image(fn=self._fetch_image,
target=basepath('ramdisk'),
- fname=disk_images['ramdisk_id'],
+ fname=fname,
image_id=disk_images['ramdisk_id'],
user=user,
project=project)
- root_fname = disk_images['image_id']
+ root_fname = '%08x' % int(disk_images['image_id'])
size = FLAGS.minimum_root_size
if inst['instance_type'] == 'm1.tiny' or suffix == '.rescue':
size = None