This change set adds the ability to create new servers with an href that points to a server image on any glance server (not only the default one configured). This means you can create a server with imageRef = http://glance1:9292/images/3 and then also create one with imageRef = http://glance2:9292/images/1. Using the old way of passing in an image_id still works as well, and will use the default configured glance server (imageRef = 3 for instance).
We have tested pretty thoroughly with libvirt and xen. All tests pass, and we have done full end-to-end testing manually to verify that server creation/deletion is working.
This commit is contained in:
commit
0fd5e0ca8b
@ -78,6 +78,7 @@ from nova import crypto
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import image
|
||||
from nova import log as logging
|
||||
from nova import quota
|
||||
from nova import rpc
|
||||
@ -936,7 +937,7 @@ class ImageCommands(object):
|
||||
"""Methods for dealing with a cloud in an odd state"""
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.image_service = utils.import_object(FLAGS.image_service)
|
||||
self.image_service = image.get_default_image_service()
|
||||
|
||||
def _register(self, container_format, disk_format,
|
||||
path, owner, name=None, is_public='T',
|
||||
|
@ -159,7 +159,7 @@ 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'])
|
||||
image_ec2_id = self.image_ec2_id(instance_ref['image_ref'])
|
||||
data = {
|
||||
'user-data': base64.b64decode(instance_ref['user_data']),
|
||||
'meta-data': {
|
||||
@ -774,13 +774,13 @@ class CloudController(object):
|
||||
instances = self.compute_api.get_all(context, **kwargs)
|
||||
for instance in instances:
|
||||
if not context.is_admin:
|
||||
if instance['image_id'] == str(FLAGS.vpn_image_id):
|
||||
if instance['image_ref'] == str(FLAGS.vpn_image_id):
|
||||
continue
|
||||
i = {}
|
||||
instance_id = instance['id']
|
||||
ec2_id = ec2utils.id_to_ec2_id(instance_id)
|
||||
i['instanceId'] = ec2_id
|
||||
i['imageId'] = self.image_ec2_id(instance['image_id'])
|
||||
i['imageId'] = self.image_ec2_id(instance['image_ref'])
|
||||
i['instanceState'] = {
|
||||
'code': instance['state'],
|
||||
'name': instance['state_description']}
|
||||
@ -899,7 +899,7 @@ class CloudController(object):
|
||||
instances = self.compute_api.create(context,
|
||||
instance_type=instance_types.get_instance_type_by_name(
|
||||
kwargs.get('instance_type', None)),
|
||||
image_id=self._get_image(context, kwargs['image_id'])['id'],
|
||||
image_href=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'),
|
||||
@ -975,7 +975,12 @@ class CloudController(object):
|
||||
def image_ec2_id(image_id, image_type='ami'):
|
||||
"""Returns image ec2_id using id and three letter type."""
|
||||
template = image_type + '-%08x'
|
||||
return ec2utils.id_to_ec2_id(int(image_id), template=template)
|
||||
try:
|
||||
return ec2utils.id_to_ec2_id(int(image_id), template=template)
|
||||
except ValueError:
|
||||
#TODO(wwolf): once we have ec2_id -> glance_id mapping
|
||||
# in place, this wont be necessary
|
||||
return "ami-00000000"
|
||||
|
||||
def _get_image(self, context, ec2_id):
|
||||
try:
|
||||
|
@ -99,34 +99,6 @@ def limited_by_marker(items, request, max_limit=FLAGS.osapi_max_limit):
|
||||
return items[start_index:range_end]
|
||||
|
||||
|
||||
def get_image_id_from_image_hash(image_service, context, image_hash):
|
||||
"""Given an Image ID Hash, return an objectstore Image ID.
|
||||
|
||||
image_service - reference to objectstore compatible image service.
|
||||
context - security context for image service requests.
|
||||
image_hash - hash of the image ID.
|
||||
"""
|
||||
|
||||
# FIX(sandy): This is terribly inefficient. It pulls all images
|
||||
# from objectstore in order to find the match. ObjectStore
|
||||
# should have a numeric counterpart to the string ID.
|
||||
try:
|
||||
items = image_service.detail(context)
|
||||
except NotImplementedError:
|
||||
items = image_service.index(context)
|
||||
for image in items:
|
||||
image_id = image['id']
|
||||
try:
|
||||
if abs(hash(image_id)) == int(image_hash):
|
||||
return image_id
|
||||
except ValueError:
|
||||
msg = _("Requested image_id has wrong format: %s,"
|
||||
"should have numerical format") % image_id
|
||||
LOG.error(msg)
|
||||
raise Exception(msg)
|
||||
raise exception.ImageNotFound(image_id=image_hash)
|
||||
|
||||
|
||||
def get_id_from_href(href):
|
||||
"""Return the id portion of a url as an int.
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
||||
from webob import exc
|
||||
|
||||
from nova import flags
|
||||
from nova import image
|
||||
from nova import quota
|
||||
from nova import utils
|
||||
from nova.api.openstack import faults
|
||||
@ -31,7 +32,7 @@ class Controller(object):
|
||||
"""The image metadata API controller for the Openstack API"""
|
||||
|
||||
def __init__(self):
|
||||
self.image_service = utils.import_object(FLAGS.image_service)
|
||||
self.image_service = image.get_default_image_service()
|
||||
|
||||
def _get_metadata(self, context, image_id, image=None):
|
||||
if not image:
|
||||
|
@ -18,6 +18,7 @@ import webob.exc
|
||||
from nova import compute
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log
|
||||
from nova import utils
|
||||
from nova.api.openstack import common
|
||||
@ -40,11 +41,11 @@ class Controller(object):
|
||||
|
||||
:param compute_service: `nova.compute.api:API`
|
||||
:param image_service: `nova.image.service:BaseImageService`
|
||||
"""
|
||||
_default_service = utils.import_object(flags.FLAGS.image_service)
|
||||
|
||||
"""
|
||||
self._compute_service = compute_service or compute.API()
|
||||
self._image_service = image_service or _default_service
|
||||
self._image_service = image_service or \
|
||||
nova.image.get_default_image_service()
|
||||
|
||||
def index(self, req):
|
||||
"""Return an index listing of images available to the request.
|
||||
@ -88,22 +89,16 @@ class Controller(object):
|
||||
"""Return detailed information about a specific image.
|
||||
|
||||
:param req: `wsgi.Request` object
|
||||
:param id: Image identifier (integer)
|
||||
:param id: Image identifier
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
|
||||
try:
|
||||
image_id = int(id)
|
||||
except ValueError:
|
||||
image = self._image_service.show(context, id)
|
||||
except (exception.NotFound, exception.InvalidImageRef):
|
||||
explanation = _("Image not found.")
|
||||
raise faults.Fault(webob.exc.HTTPNotFound(explanation=explanation))
|
||||
|
||||
try:
|
||||
image = self._image_service.show(context, image_id)
|
||||
except exception.NotFound:
|
||||
explanation = _("Image '%d' not found.") % (image_id)
|
||||
raise faults.Fault(webob.exc.HTTPNotFound(explanation=explanation))
|
||||
|
||||
return dict(image=self.get_builder(req).build(image, detail=True))
|
||||
|
||||
def delete(self, req, id):
|
||||
@ -112,9 +107,8 @@ class Controller(object):
|
||||
:param req: `wsgi.Request` object
|
||||
:param id: Image identifier (integer)
|
||||
"""
|
||||
image_id = id
|
||||
context = req.environ['nova.context']
|
||||
self._image_service.delete(context, image_id)
|
||||
self._image_service.delete(context, id)
|
||||
return webob.exc.HTTPNoContent()
|
||||
|
||||
def create(self, req, body):
|
||||
|
@ -22,6 +22,7 @@ from xml.dom import minidom
|
||||
from nova import compute
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log as logging
|
||||
from nova import quota
|
||||
from nova import utils
|
||||
@ -51,13 +52,21 @@ class Controller(object):
|
||||
|
||||
def index(self, req):
|
||||
""" Returns a list of server names and ids for a given user """
|
||||
return self._items(req, is_detail=False)
|
||||
try:
|
||||
servers = self._items(req, is_detail=False)
|
||||
except exception.Invalid as err:
|
||||
return exc.HTTPBadRequest(str(err))
|
||||
return servers
|
||||
|
||||
def detail(self, req):
|
||||
""" Returns a list of server details for a given user """
|
||||
return self._items(req, is_detail=True)
|
||||
try:
|
||||
servers = self._items(req, is_detail=True)
|
||||
except exception.Invalid as err:
|
||||
return exc.HTTPBadRequest(str(err))
|
||||
return servers
|
||||
|
||||
def _image_id_from_req_data(self, data):
|
||||
def _image_ref_from_req_data(self, data):
|
||||
raise NotImplementedError()
|
||||
|
||||
def _flavor_id_from_req_data(self, data):
|
||||
@ -121,18 +130,19 @@ class Controller(object):
|
||||
key_name = key_pair['name']
|
||||
key_data = key_pair['public_key']
|
||||
|
||||
requested_image_id = self._image_id_from_req_data(body)
|
||||
image_href = self._image_ref_from_req_data(body)
|
||||
try:
|
||||
image_id = common.get_image_id_from_image_hash(self._image_service,
|
||||
context, requested_image_id)
|
||||
image_service, image_id = nova.image.get_image_service(image_href)
|
||||
kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(
|
||||
req, image_service, image_id)
|
||||
images = set([str(x['id']) for x in image_service.index(context)])
|
||||
assert str(image_id) in images
|
||||
except:
|
||||
msg = _("Can not find requested image")
|
||||
msg = _("Cannot find requested image %s") % image_href
|
||||
return faults.Fault(exc.HTTPBadRequest(msg))
|
||||
|
||||
kernel_id, ramdisk_id = self._get_kernel_ramdisk_from_image(
|
||||
req, image_id)
|
||||
|
||||
personality = body['server'].get('personality')
|
||||
|
||||
injected_files = []
|
||||
if personality:
|
||||
injected_files = self._get_injected_files(personality)
|
||||
@ -153,7 +163,7 @@ class Controller(object):
|
||||
(inst,) = self.compute_api.create(
|
||||
context,
|
||||
inst_type,
|
||||
image_id,
|
||||
image_href,
|
||||
kernel_id=kernel_id,
|
||||
ramdisk_id=ramdisk_id,
|
||||
display_name=name,
|
||||
@ -165,9 +175,12 @@ class Controller(object):
|
||||
admin_password=password)
|
||||
except quota.QuotaError as error:
|
||||
self._handle_quota_error(error)
|
||||
except exception.ImageNotFound as error:
|
||||
msg = _("Can not find requested image")
|
||||
return faults.Fault(exc.HTTPBadRequest(msg))
|
||||
|
||||
inst['instance_type'] = inst_type
|
||||
inst['image_id'] = requested_image_id
|
||||
inst['image_ref'] = image_href
|
||||
|
||||
builder = self._get_view_builder(req)
|
||||
server = builder.build(inst, is_detail=True)
|
||||
@ -505,17 +518,15 @@ class Controller(object):
|
||||
error=item.error))
|
||||
return dict(actions=actions)
|
||||
|
||||
def _get_kernel_ramdisk_from_image(self, req, image_id):
|
||||
def _get_kernel_ramdisk_from_image(self, req, image_service, image_id):
|
||||
"""Fetch an image from the ImageService, then if present, return the
|
||||
associated kernel and ramdisk image IDs.
|
||||
"""
|
||||
context = req.environ['nova.context']
|
||||
image_meta = self._image_service.show(context, image_id)
|
||||
image_meta = image_service.show(context, image_id)
|
||||
# NOTE(sirp): extracted to a separate method to aid unit-testing, the
|
||||
# new method doesn't need a request obj or an ImageService stub
|
||||
kernel_id, ramdisk_id = self._do_get_kernel_ramdisk_from_image(
|
||||
image_meta)
|
||||
return kernel_id, ramdisk_id
|
||||
return self._do_get_kernel_ramdisk_from_image(image_meta)
|
||||
|
||||
@staticmethod
|
||||
def _do_get_kernel_ramdisk_from_image(image_meta):
|
||||
@ -546,7 +557,7 @@ class Controller(object):
|
||||
|
||||
|
||||
class ControllerV10(Controller):
|
||||
def _image_id_from_req_data(self, data):
|
||||
def _image_ref_from_req_data(self, data):
|
||||
return data['server']['imageId']
|
||||
|
||||
def _flavor_id_from_req_data(self, data):
|
||||
@ -604,9 +615,8 @@ class ControllerV10(Controller):
|
||||
|
||||
|
||||
class ControllerV11(Controller):
|
||||
def _image_id_from_req_data(self, data):
|
||||
href = data['server']['imageRef']
|
||||
return common.get_id_from_href(href)
|
||||
def _image_ref_from_req_data(self, data):
|
||||
return data['server']['imageRef']
|
||||
|
||||
def _flavor_id_from_req_data(self, data):
|
||||
href = data['server']['flavorRef']
|
||||
@ -686,13 +696,12 @@ class ControllerV11(Controller):
|
||||
instance_id = int(instance_id)
|
||||
|
||||
try:
|
||||
image_ref = info["rebuild"]["imageRef"]
|
||||
image_href = info["rebuild"]["imageRef"]
|
||||
except (KeyError, TypeError):
|
||||
msg = _("Could not parse imageRef from request.")
|
||||
LOG.debug(msg)
|
||||
return faults.Fault(exc.HTTPBadRequest(explanation=msg))
|
||||
|
||||
image_id = common.get_id_from_href(image_ref)
|
||||
personalities = info["rebuild"].get("personality", [])
|
||||
metadata = info["rebuild"].get("metadata")
|
||||
name = info["rebuild"].get("name")
|
||||
@ -702,7 +711,7 @@ class ControllerV11(Controller):
|
||||
self._decode_personalities(personalities)
|
||||
|
||||
try:
|
||||
self.compute_api.rebuild(context, instance_id, image_id, name,
|
||||
self.compute_api.rebuild(context, instance_id, image_href, name,
|
||||
metadata, personalities)
|
||||
except exception.BuildInProgress:
|
||||
msg = _("Instance %d is currently being rebuilt.") % instance_id
|
||||
|
@ -18,6 +18,7 @@
|
||||
import hashlib
|
||||
import os
|
||||
|
||||
from nova import exception
|
||||
from nova.compute import power_state
|
||||
import nova.compute
|
||||
import nova.context
|
||||
@ -112,8 +113,11 @@ class ViewBuilderV10(ViewBuilder):
|
||||
"""Model an Openstack API V1.0 server response."""
|
||||
|
||||
def _build_image(self, response, inst):
|
||||
if 'image_id' in dict(inst):
|
||||
response['imageId'] = inst['image_id']
|
||||
if 'image_ref' in dict(inst):
|
||||
image_ref = inst['image_ref']
|
||||
if str(image_ref).startswith('http'):
|
||||
raise exception.ListingImageRefsNotSupported()
|
||||
response['imageId'] = int(image_ref)
|
||||
|
||||
def _build_flavor(self, response, inst):
|
||||
if 'instance_type' in dict(inst):
|
||||
@ -130,9 +134,11 @@ class ViewBuilderV11(ViewBuilder):
|
||||
self.base_url = base_url
|
||||
|
||||
def _build_image(self, response, inst):
|
||||
if "image_id" in dict(inst):
|
||||
image_id = inst.get("image_id")
|
||||
response["imageRef"] = self.image_builder.generate_href(image_id)
|
||||
if 'image_ref' in dict(inst):
|
||||
image_href = inst['image_ref']
|
||||
if str(image_href).isdigit():
|
||||
image_href = int(image_href)
|
||||
response['imageRef'] = image_href
|
||||
|
||||
def _build_flavor(self, response, inst):
|
||||
if "instance_type" in dict(inst):
|
||||
|
@ -26,6 +26,7 @@ import time
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log as logging
|
||||
from nova import network
|
||||
from nova import quota
|
||||
@ -58,9 +59,9 @@ class API(base.Base):
|
||||
def __init__(self, image_service=None, network_api=None,
|
||||
volume_api=None, hostname_factory=generate_default_hostname,
|
||||
**kwargs):
|
||||
if not image_service:
|
||||
image_service = utils.import_object(FLAGS.image_service)
|
||||
self.image_service = image_service
|
||||
self.image_service = image_service or \
|
||||
nova.image.get_default_image_service()
|
||||
|
||||
if not network_api:
|
||||
network_api = network.API()
|
||||
self.network_api = network_api
|
||||
@ -129,7 +130,7 @@ class API(base.Base):
|
||||
raise quota.QuotaError(msg, "MetadataLimitExceeded")
|
||||
|
||||
def create(self, context, instance_type,
|
||||
image_id, kernel_id=None, ramdisk_id=None,
|
||||
image_href, kernel_id=None, ramdisk_id=None,
|
||||
min_count=1, max_count=1,
|
||||
display_name='', display_description='',
|
||||
key_name=None, key_data=None, security_group='default',
|
||||
@ -160,7 +161,8 @@ class API(base.Base):
|
||||
self._check_metadata_properties_quota(context, metadata)
|
||||
self._check_injected_file_quota(context, injected_files)
|
||||
|
||||
image = self.image_service.show(context, image_id)
|
||||
(image_service, image_id) = nova.image.get_image_service(image_href)
|
||||
image = image_service.show(context, image_id)
|
||||
|
||||
os_type = None
|
||||
if 'properties' in image and 'os_type' in image['properties']:
|
||||
@ -180,9 +182,9 @@ class API(base.Base):
|
||||
logging.debug("Using Kernel=%s, Ramdisk=%s" %
|
||||
(kernel_id, ramdisk_id))
|
||||
if kernel_id:
|
||||
self.image_service.show(context, kernel_id)
|
||||
image_service.show(context, kernel_id)
|
||||
if ramdisk_id:
|
||||
self.image_service.show(context, ramdisk_id)
|
||||
image_service.show(context, ramdisk_id)
|
||||
|
||||
if security_group is None:
|
||||
security_group = ['default']
|
||||
@ -203,7 +205,7 @@ class API(base.Base):
|
||||
|
||||
base_options = {
|
||||
'reservation_id': utils.generate_uid('r'),
|
||||
'image_id': image_id,
|
||||
'image_ref': image_href,
|
||||
'kernel_id': kernel_id or '',
|
||||
'ramdisk_id': ramdisk_id or '',
|
||||
'state': 0,
|
||||
@ -529,8 +531,8 @@ class API(base.Base):
|
||||
"""Reboot the given instance."""
|
||||
self._cast_compute_message('reboot_instance', context, instance_id)
|
||||
|
||||
def rebuild(self, context, instance_id, image_id, name=None, metadata=None,
|
||||
files_to_inject=None):
|
||||
def rebuild(self, context, instance_id, image_href, name=None,
|
||||
metadata=None, files_to_inject=None):
|
||||
"""Rebuild the given instance with the provided metadata."""
|
||||
instance = db.api.instance_get(context, instance_id)
|
||||
|
||||
@ -550,7 +552,7 @@ class API(base.Base):
|
||||
self.db.instance_update(context, instance_id, values)
|
||||
|
||||
rebuild_params = {
|
||||
"image_id": image_id,
|
||||
"image_ref": image_href,
|
||||
"injected_files": files_to_inject,
|
||||
}
|
||||
|
||||
|
@ -162,9 +162,9 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
data = {'launched_at': launched_at or datetime.datetime.utcnow()}
|
||||
self.db.instance_update(context, instance_id, data)
|
||||
|
||||
def _update_image_id(self, context, instance_id, image_id):
|
||||
def _update_image_ref(self, context, instance_id, image_ref):
|
||||
"""Update the image_id for the given instance."""
|
||||
data = {'image_id': image_id}
|
||||
data = {'image_ref': image_ref}
|
||||
self.db.instance_update(context, instance_id, data)
|
||||
|
||||
def get_console_topic(self, context, **kwargs):
|
||||
@ -235,7 +235,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
power_state.NOSTATE,
|
||||
'networking')
|
||||
|
||||
is_vpn = instance_ref['image_id'] == str(FLAGS.vpn_image_id)
|
||||
is_vpn = instance_ref['image_ref'] == str(FLAGS.vpn_image_id)
|
||||
# NOTE(vish): This could be a cast because we don't do anything
|
||||
# with the address currently, but I'm leaving it as
|
||||
# a call to ensure that network setup completes. We
|
||||
@ -339,7 +339,7 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
|
||||
:param context: `nova.RequestContext` object
|
||||
:param instance_id: Instance identifier (integer)
|
||||
:param image_id: Image identifier (integer)
|
||||
:param image_ref: Image identifier (href or integer)
|
||||
"""
|
||||
context = context.elevated()
|
||||
|
||||
@ -349,11 +349,12 @@ class ComputeManager(manager.SchedulerDependentManager):
|
||||
self._update_state(context, instance_id, power_state.BUILDING)
|
||||
|
||||
self.driver.destroy(instance_ref)
|
||||
instance_ref.image_id = kwargs.get('image_id')
|
||||
image_ref = kwargs.get('image_ref')
|
||||
instance_ref.image_ref = image_ref
|
||||
instance_ref.injected_files = kwargs.get('injected_files', [])
|
||||
self.driver.spawn(instance_ref)
|
||||
|
||||
self._update_image_id(context, instance_id, image_id)
|
||||
self._update_image_ref(context, instance_id, image_ref)
|
||||
self._update_launched_at(context, instance_id)
|
||||
self._update_state(context, instance_id)
|
||||
|
||||
|
@ -956,7 +956,7 @@ def instance_get_project_vpn(context, project_id):
|
||||
options(joinedload('security_groups')).\
|
||||
options(joinedload('instance_type')).\
|
||||
filter_by(project_id=project_id).\
|
||||
filter_by(image_id=str(FLAGS.vpn_image_id)).\
|
||||
filter_by(image_ref=str(FLAGS.vpn_image_id)).\
|
||||
filter_by(deleted=can_read_deleted(context)).\
|
||||
first()
|
||||
|
||||
|
@ -0,0 +1,40 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2011 OpenStack LLC.
|
||||
#
|
||||
# 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.
|
||||
|
||||
from sqlalchemy import Column, Integer, MetaData, String, Table
|
||||
|
||||
|
||||
meta = MetaData()
|
||||
|
||||
|
||||
def upgrade(migrate_engine):
|
||||
# Upgrade operations go here. Don't create your own engine;
|
||||
# bind migrate_engine to your metadata
|
||||
meta.bind = migrate_engine
|
||||
instances = Table('instances', meta, autoload=True,
|
||||
autoload_with=migrate_engine)
|
||||
|
||||
image_id_column = instances.c.image_id
|
||||
image_id_column.alter(name='image_ref')
|
||||
|
||||
|
||||
def downgrade(migrate_engine):
|
||||
meta.bind = migrate_engine
|
||||
instances = Table('instances', meta, autoload=True,
|
||||
autoload_with=migrate_engine)
|
||||
|
||||
image_ref_column = instances.c.image_ref
|
||||
image_ref_column.alter(name='image_id')
|
@ -184,11 +184,11 @@ class Instance(BASE, NovaBase):
|
||||
def project(self):
|
||||
return auth.manager.AuthManager().get_project(self.project_id)
|
||||
|
||||
image_id = Column(String(255))
|
||||
image_ref = Column(String(255))
|
||||
kernel_id = Column(String(255))
|
||||
ramdisk_id = Column(String(255))
|
||||
|
||||
# image_id = Column(Integer, ForeignKey('images.id'), nullable=True)
|
||||
# image_ref = Column(Integer, ForeignKey('images.id'), nullable=True)
|
||||
# kernel_id = Column(Integer, ForeignKey('images.id'), nullable=True)
|
||||
# ramdisk_id = Column(Integer, ForeignKey('images.id'), nullable=True)
|
||||
# ramdisk = relationship(Ramdisk, backref=backref('instances', order_by=id))
|
||||
|
@ -291,6 +291,15 @@ class DiskNotFound(NotFound):
|
||||
message = _("No disk at %(location)s")
|
||||
|
||||
|
||||
class InvalidImageRef(Invalid):
|
||||
message = _("Invalid image href %(image_href)s.")
|
||||
|
||||
|
||||
class ListingImageRefsNotSupported(Invalid):
|
||||
message = _("Some images have been stored via hrefs."
|
||||
+ " This version of the api does not support displaying image hrefs.")
|
||||
|
||||
|
||||
class ImageNotFound(NotFound):
|
||||
message = _("Image %(image_id)s could not be found.")
|
||||
|
||||
|
@ -0,0 +1,93 @@
|
||||
# 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.
|
||||
|
||||
|
||||
from urlparse import urlparse
|
||||
|
||||
import nova
|
||||
from nova import exception
|
||||
from nova import utils
|
||||
from nova import flags
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
|
||||
|
||||
GlanceClient = utils.import_class('glance.client.Client')
|
||||
|
||||
|
||||
def _parse_image_ref(image_href):
|
||||
"""Parse an image href into composite parts.
|
||||
|
||||
:param image_href: href of an image
|
||||
:returns: a tuple of the form (image_id, host, port)
|
||||
|
||||
"""
|
||||
o = urlparse(image_href)
|
||||
port = o.port or 80
|
||||
host = o.netloc.split(':', 1)[0]
|
||||
image_id = int(o.path.split('/')[-1])
|
||||
return (image_id, host, port)
|
||||
|
||||
|
||||
def get_default_image_service():
|
||||
ImageService = utils.import_class(FLAGS.image_service)
|
||||
return ImageService()
|
||||
|
||||
|
||||
def get_glance_client(image_href):
|
||||
"""Get the correct glance client and id for the given image_href.
|
||||
|
||||
The image_href param can be an href of the form
|
||||
http://myglanceserver:9292/images/42, or just an int such as 42. If the
|
||||
image_href is an int, then flags are used to create the default
|
||||
glance client.
|
||||
|
||||
:param image_href: image ref/id for an image
|
||||
:returns: a tuple of the form (glance_client, image_id)
|
||||
|
||||
"""
|
||||
image_href = image_href or 0
|
||||
if str(image_href).isdigit():
|
||||
glance_client = GlanceClient(FLAGS.glance_host, FLAGS.glance_port)
|
||||
return (glance_client, int(image_href))
|
||||
|
||||
try:
|
||||
(image_id, host, port) = _parse_image_ref(image_href)
|
||||
except:
|
||||
raise exception.InvalidImageRef(image_href=image_href)
|
||||
glance_client = GlanceClient(host, port)
|
||||
return (glance_client, image_id)
|
||||
|
||||
|
||||
def get_image_service(image_href):
|
||||
"""Get the proper image_service and id for the given image_href.
|
||||
|
||||
The image_href param can be an href of the form
|
||||
http://myglanceserver:9292/images/42, or just an int such as 42. If the
|
||||
image_href is an int, then the default image service is returned.
|
||||
|
||||
:param image_href: image ref/id for an image
|
||||
:returns: a tuple of the form (image_service, image_id)
|
||||
|
||||
"""
|
||||
image_href = image_href or 0
|
||||
if str(image_href).isdigit():
|
||||
return (get_default_image_service(), int(image_href))
|
||||
|
||||
(glance_client, image_id) = get_glance_client(image_href)
|
||||
image_service = nova.image.glance.GlanceImageService(glance_client)
|
||||
return (image_service, image_id)
|
@ -41,7 +41,7 @@ class _FakeImageService(service.BaseImageService):
|
||||
# NOTE(justinsb): The OpenStack API can't upload an image?
|
||||
# So, make sure we've got one..
|
||||
timestamp = datetime.datetime(2011, 01, 01, 01, 02, 03)
|
||||
image = {'id': '123456',
|
||||
image1 = {'id': '123456',
|
||||
'name': 'fakeimage123456',
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
@ -51,7 +51,52 @@ class _FakeImageService(service.BaseImageService):
|
||||
'properties': {'kernel_id': FLAGS.null_kernel,
|
||||
'ramdisk_id': FLAGS.null_kernel,
|
||||
'architecture': 'x86_64'}}
|
||||
self.create(None, image)
|
||||
|
||||
image2 = {'id': 'fake',
|
||||
'name': 'fakeimage123456',
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'status': 'active',
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'raw',
|
||||
'properties': {'kernel_id': FLAGS.null_kernel,
|
||||
'ramdisk_id': FLAGS.null_kernel}}
|
||||
|
||||
image3 = {'id': '2',
|
||||
'name': 'fakeimage123456',
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'status': 'active',
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'raw',
|
||||
'properties': {'kernel_id': FLAGS.null_kernel,
|
||||
'ramdisk_id': FLAGS.null_kernel}}
|
||||
|
||||
image4 = {'id': '1',
|
||||
'name': 'fakeimage123456',
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'status': 'active',
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'raw',
|
||||
'properties': {'kernel_id': FLAGS.null_kernel,
|
||||
'ramdisk_id': FLAGS.null_kernel}}
|
||||
|
||||
image5 = {'id': '3',
|
||||
'name': 'fakeimage123456',
|
||||
'created_at': timestamp,
|
||||
'updated_at': timestamp,
|
||||
'status': 'active',
|
||||
'container_format': 'ami',
|
||||
'disk_format': 'raw',
|
||||
'properties': {'kernel_id': FLAGS.null_kernel,
|
||||
'ramdisk_id': FLAGS.null_kernel}}
|
||||
|
||||
self.create(None, image1)
|
||||
self.create(None, image2)
|
||||
self.create(None, image3)
|
||||
self.create(None, image4)
|
||||
self.create(None, image5)
|
||||
super(_FakeImageService, self).__init__()
|
||||
|
||||
def index(self, context, filters=None):
|
||||
@ -68,8 +113,7 @@ class _FakeImageService(service.BaseImageService):
|
||||
Returns a dict containing image data for the given opaque image id.
|
||||
|
||||
"""
|
||||
image_id = int(image_id)
|
||||
image = self.images.get(image_id)
|
||||
image = self.images.get(str(image_id))
|
||||
if image:
|
||||
return copy.deepcopy(image)
|
||||
LOG.warn('Unable to find image id %s. Have images: %s',
|
||||
@ -83,9 +127,10 @@ class _FakeImageService(service.BaseImageService):
|
||||
|
||||
"""
|
||||
try:
|
||||
image_id = int(metadata['id'])
|
||||
image_id = metadata['id']
|
||||
except KeyError:
|
||||
image_id = random.randint(0, 2 ** 31 - 1)
|
||||
image_id = str(image_id)
|
||||
|
||||
if self.images.get(image_id):
|
||||
raise exception.Duplicate()
|
||||
@ -100,7 +145,6 @@ class _FakeImageService(service.BaseImageService):
|
||||
:raises: ImageNotFound if the image does not exist.
|
||||
|
||||
"""
|
||||
image_id = int(image_id)
|
||||
if not self.images.get(image_id):
|
||||
raise exception.ImageNotFound(image_id=image_id)
|
||||
self.images[image_id] = copy.deepcopy(metadata)
|
||||
@ -111,7 +155,6 @@ class _FakeImageService(service.BaseImageService):
|
||||
:raises: ImageNotFound if the image does not exist.
|
||||
|
||||
"""
|
||||
image_id = int(image_id)
|
||||
removed = self.images.pop(image_id, None)
|
||||
if not removed:
|
||||
raise exception.ImageNotFound(image_id=image_id)
|
||||
|
@ -31,6 +31,7 @@ import eventlet
|
||||
from nova import crypto
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import image
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
from nova.auth import manager
|
||||
@ -48,9 +49,7 @@ class S3ImageService(service.BaseImageService):
|
||||
"""Wraps an existing image service to support s3 based register."""
|
||||
|
||||
def __init__(self, service=None, *args, **kwargs):
|
||||
if service is None:
|
||||
service = utils.import_object(FLAGS.image_service)
|
||||
self.service = service
|
||||
self.service = service or image.get_default_image_service()
|
||||
self.service.__init__(*args, **kwargs)
|
||||
|
||||
def create(self, context, metadata, data=None):
|
||||
|
@ -38,6 +38,7 @@ from nova.api.openstack import auth
|
||||
from nova.api.openstack import versions
|
||||
from nova.api.openstack import limits
|
||||
from nova.auth.manager import User, Project
|
||||
import nova.image.fake
|
||||
from nova.image import glance
|
||||
from nova.image import local
|
||||
from nova.image import service
|
||||
@ -104,10 +105,12 @@ def stub_out_key_pair_funcs(stubs, have_key_pair=True):
|
||||
|
||||
|
||||
def stub_out_image_service(stubs):
|
||||
def fake_image_show(meh, context, id):
|
||||
return dict(kernelId=1, ramdiskId=1)
|
||||
|
||||
stubs.Set(local.LocalImageService, 'show', fake_image_show)
|
||||
def fake_get_image_service(image_href):
|
||||
image_id = int(str(image_href).split('/')[-1])
|
||||
return (nova.image.fake.FakeImageService(), image_id)
|
||||
stubs.Set(nova.image, 'get_image_service', fake_get_image_service)
|
||||
stubs.Set(nova.image, 'get_default_image_service',
|
||||
lambda: nova.image.fake.FakeImageService())
|
||||
|
||||
|
||||
def stub_out_auth(stubs):
|
||||
@ -208,7 +211,7 @@ def stub_out_glance(stubs, initial_fixtures=None):
|
||||
|
||||
def _find_image(self, image_id):
|
||||
for f in self.fixtures:
|
||||
if f['id'] == image_id:
|
||||
if str(f['id']) == str(image_id):
|
||||
return f
|
||||
return None
|
||||
|
||||
|
@ -37,6 +37,7 @@ from nova.compute import power_state
|
||||
import nova.db.api
|
||||
from nova.db.sqlalchemy.models import Instance
|
||||
from nova.db.sqlalchemy.models import InstanceMetadata
|
||||
import nova.image.fake
|
||||
import nova.rpc
|
||||
from nova.tests.api.openstack import common
|
||||
from nova.tests.api.openstack import fakes
|
||||
@ -97,7 +98,7 @@ def stub_instance(id, user_id=1, private_address=None, public_addresses=None,
|
||||
"admin_pass": "",
|
||||
"user_id": user_id,
|
||||
"project_id": "",
|
||||
"image_id": "10",
|
||||
"image_ref": "10",
|
||||
"kernel_id": "",
|
||||
"ramdisk_id": "",
|
||||
"launch_index": 0,
|
||||
@ -484,8 +485,6 @@ class ServersTest(test.TestCase):
|
||||
fake_method)
|
||||
self.stubs.Set(nova.api.openstack.servers.Controller,
|
||||
"_get_kernel_ramdisk_from_image", kernel_ramdisk_mapping)
|
||||
self.stubs.Set(nova.api.openstack.common,
|
||||
"get_image_id_from_image_hash", image_id_from_hash)
|
||||
self.stubs.Set(nova.compute.api.API, "_find_host", find_host)
|
||||
|
||||
def _test_create_instance_helper(self):
|
||||
@ -588,12 +587,12 @@ class ServersTest(test.TestCase):
|
||||
def test_create_instance_v1_1(self):
|
||||
self._setup_for_create_instance()
|
||||
|
||||
image_ref = 'http://localhost/v1.1/images/2'
|
||||
image_href = 'http://localhost/v1.1/images/2'
|
||||
flavor_ref = 'http://localhost/v1.1/flavors/3'
|
||||
body = {
|
||||
'server': {
|
||||
'name': 'server_test',
|
||||
'imageRef': image_ref,
|
||||
'imageRef': image_href,
|
||||
'flavorRef': flavor_ref,
|
||||
'metadata': {
|
||||
'hello': 'world',
|
||||
@ -615,16 +614,16 @@ class ServersTest(test.TestCase):
|
||||
self.assertEqual('server_test', server['name'])
|
||||
self.assertEqual(1, server['id'])
|
||||
self.assertEqual(flavor_ref, server['flavorRef'])
|
||||
self.assertEqual(image_ref, server['imageRef'])
|
||||
self.assertEqual(image_href, server['imageRef'])
|
||||
self.assertEqual(res.status_int, 200)
|
||||
|
||||
def test_create_instance_v1_1_bad_href(self):
|
||||
self._setup_for_create_instance()
|
||||
|
||||
image_ref = 'http://localhost/v1.1/images/asdf'
|
||||
image_href = 'http://localhost/v1.1/images/asdf'
|
||||
flavor_ref = 'http://localhost/v1.1/flavors/3'
|
||||
body = dict(server=dict(
|
||||
name='server_test', imageRef=image_ref, flavorRef=flavor_ref,
|
||||
name='server_test', imageRef=image_href, flavorRef=flavor_ref,
|
||||
metadata={'hello': 'world', 'open': 'stack'},
|
||||
personality={}))
|
||||
req = webob.Request.blank('/v1.1/servers')
|
||||
@ -637,13 +636,12 @@ class ServersTest(test.TestCase):
|
||||
def test_create_instance_v1_1_local_href(self):
|
||||
self._setup_for_create_instance()
|
||||
|
||||
image_ref = 'http://localhost/v1.1/images/2'
|
||||
image_ref_local = '2'
|
||||
image_id = 2
|
||||
flavor_ref = 'http://localhost/v1.1/flavors/3'
|
||||
body = {
|
||||
'server': {
|
||||
'name': 'server_test',
|
||||
'imageRef': image_ref_local,
|
||||
'imageRef': image_id,
|
||||
'flavorRef': flavor_ref,
|
||||
},
|
||||
}
|
||||
@ -658,7 +656,7 @@ class ServersTest(test.TestCase):
|
||||
server = json.loads(res.body)['server']
|
||||
self.assertEqual(1, server['id'])
|
||||
self.assertEqual(flavor_ref, server['flavorRef'])
|
||||
self.assertEqual(image_ref, server['imageRef'])
|
||||
self.assertEqual(image_id, server['imageRef'])
|
||||
self.assertEqual(res.status_int, 200)
|
||||
|
||||
def test_create_instance_with_admin_pass_v1_0(self):
|
||||
@ -685,12 +683,12 @@ class ServersTest(test.TestCase):
|
||||
def test_create_instance_with_admin_pass_v1_1(self):
|
||||
self._setup_for_create_instance()
|
||||
|
||||
image_ref = 'http://localhost/v1.1/images/2'
|
||||
image_href = 'http://localhost/v1.1/images/2'
|
||||
flavor_ref = 'http://localhost/v1.1/flavors/3'
|
||||
body = {
|
||||
'server': {
|
||||
'name': 'server_test',
|
||||
'imageRef': image_ref,
|
||||
'imageRef': image_href,
|
||||
'flavorRef': flavor_ref,
|
||||
'adminPass': 'testpass',
|
||||
},
|
||||
@ -707,12 +705,12 @@ class ServersTest(test.TestCase):
|
||||
def test_create_instance_with_empty_admin_pass_v1_1(self):
|
||||
self._setup_for_create_instance()
|
||||
|
||||
image_ref = 'http://localhost/v1.1/images/2'
|
||||
image_href = 'http://localhost/v1.1/images/2'
|
||||
flavor_ref = 'http://localhost/v1.1/flavors/3'
|
||||
body = {
|
||||
'server': {
|
||||
'name': 'server_test',
|
||||
'imageRef': image_ref,
|
||||
'imageRef': image_href,
|
||||
'flavorRef': flavor_ref,
|
||||
'adminPass': '',
|
||||
},
|
||||
@ -861,7 +859,7 @@ class ServersTest(test.TestCase):
|
||||
self.assertEqual(s['id'], i)
|
||||
self.assertEqual(s['hostId'], '')
|
||||
self.assertEqual(s['name'], 'server%d' % i)
|
||||
self.assertEqual(s['imageId'], '10')
|
||||
self.assertEqual(s['imageId'], 10)
|
||||
self.assertEqual(s['flavorId'], 1)
|
||||
self.assertEqual(s['status'], 'BUILD')
|
||||
self.assertEqual(s['metadata']['seq'], str(i))
|
||||
@ -875,7 +873,7 @@ class ServersTest(test.TestCase):
|
||||
self.assertEqual(s['id'], i)
|
||||
self.assertEqual(s['hostId'], '')
|
||||
self.assertEqual(s['name'], 'server%d' % i)
|
||||
self.assertEqual(s['imageRef'], 'http://localhost/v1.1/images/10')
|
||||
self.assertEqual(s['imageRef'], 10)
|
||||
self.assertEqual(s['flavorRef'], 'http://localhost/v1.1/flavors/1')
|
||||
self.assertEqual(s['status'], 'BUILD')
|
||||
self.assertEqual(s['metadata']['seq'], str(i))
|
||||
@ -907,7 +905,7 @@ class ServersTest(test.TestCase):
|
||||
self.assertEqual(s['id'], i)
|
||||
self.assertEqual(s['hostId'], host_ids[i % 2])
|
||||
self.assertEqual(s['name'], 'server%d' % i)
|
||||
self.assertEqual(s['imageId'], '10')
|
||||
self.assertEqual(s['imageId'], 10)
|
||||
self.assertEqual(s['flavorId'], 1)
|
||||
|
||||
def test_server_pause(self):
|
||||
@ -1680,7 +1678,7 @@ b25zLiINCg0KLVJpY2hhcmQgQmFjaA==""",
|
||||
request = self.deserializer.deserialize(serial_request, 'create')
|
||||
self.assertEqual(request, expected)
|
||||
|
||||
def test_request_xmlser_with_flavor_image_ref(self):
|
||||
def test_request_xmlser_with_flavor_image_href(self):
|
||||
serial_request = """
|
||||
<server xmlns="http://docs.openstack.org/compute/api/v1.1"
|
||||
name="new-server-test"
|
||||
@ -1702,6 +1700,7 @@ class TestServerInstanceCreation(test.TestCase):
|
||||
fakes.FakeAuthManager.auth_data = {}
|
||||
fakes.FakeAuthDatabase.data = {}
|
||||
fakes.stub_out_auth(self.stubs)
|
||||
fakes.stub_out_image_service(self.stubs)
|
||||
fakes.stub_out_key_pair_funcs(self.stubs)
|
||||
self.allow_admin = FLAGS.allow_admin_api
|
||||
|
||||
@ -1736,8 +1735,6 @@ class TestServerInstanceCreation(test.TestCase):
|
||||
self.stubs.Set(nova.compute, 'API', make_stub_method(compute_api))
|
||||
self.stubs.Set(nova.api.openstack.servers.Controller,
|
||||
'_get_kernel_ramdisk_from_image', make_stub_method((1, 1)))
|
||||
self.stubs.Set(nova.api.openstack.common,
|
||||
'get_image_id_from_image_hash', make_stub_method(2))
|
||||
return compute_api
|
||||
|
||||
def _create_personality_request_dict(self, personality_files):
|
||||
|
@ -16,13 +16,14 @@
|
||||
|
||||
import StringIO
|
||||
|
||||
import glance.client
|
||||
import nova.image
|
||||
|
||||
|
||||
def stubout_glance_client(stubs, cls):
|
||||
"""Stubs out glance.client.Client"""
|
||||
stubs.Set(glance.client, 'Client',
|
||||
lambda *args, **kwargs: cls(*args, **kwargs))
|
||||
def stubout_glance_client(stubs):
|
||||
def fake_get_glance_client(image_href):
|
||||
image_id = int(str(image_href).split('/')[-1])
|
||||
return (FakeGlance('foo'), image_id)
|
||||
stubs.Set(nova.image, 'get_glance_client', fake_get_glance_client)
|
||||
|
||||
|
||||
class FakeGlance(object):
|
||||
|
@ -27,6 +27,7 @@ from nova import flags
|
||||
from nova import service
|
||||
from nova import test # For the flags
|
||||
from nova.auth import manager
|
||||
import nova.image.glance
|
||||
from nova.log import logging
|
||||
from nova.tests.integrated.api import client
|
||||
|
||||
@ -151,6 +152,11 @@ class _IntegratedTestBase(test.TestCase):
|
||||
f = self._get_flags()
|
||||
self.flags(**f)
|
||||
|
||||
def fake_get_image_service(image_href):
|
||||
image_id = int(str(image_href).split('/')[-1])
|
||||
return (nova.image.fake.FakeImageService(), image_id)
|
||||
self.stubs.Set(nova.image, 'get_image_service', fake_get_image_service)
|
||||
|
||||
# set up services
|
||||
self.start_service('compute')
|
||||
self.start_service('volume')
|
||||
@ -199,19 +205,13 @@ class _IntegratedTestBase(test.TestCase):
|
||||
LOG.debug("Image: %s" % image)
|
||||
|
||||
if 'imageRef' in image:
|
||||
image_ref = image['imageRef']
|
||||
image_href = image['imageRef']
|
||||
else:
|
||||
# NOTE(justinsb): The imageRef code hasn't yet landed
|
||||
LOG.warning("imageRef not yet in images output")
|
||||
image_ref = image['id']
|
||||
|
||||
# TODO(justinsb): This is FUBAR
|
||||
image_ref = abs(hash(image_ref))
|
||||
|
||||
image_ref = 'http://fake.server/%s' % image_ref
|
||||
image_href = image['id']
|
||||
image_href = 'http://fake.server/%s' % image_href
|
||||
|
||||
# We now have a valid imageId
|
||||
server['imageRef'] = image_ref
|
||||
server['imageRef'] = image_href
|
||||
|
||||
# Set a valid flavorId
|
||||
flavor = self.api.get_flavors()[0]
|
||||
|
@ -254,10 +254,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,
|
||||
'image_ref': 1,
|
||||
'host': 'host1'})
|
||||
inst2 = db.instance_create(self.context, {'reservation_id': 'a',
|
||||
'image_id': 1,
|
||||
'image_ref': 1,
|
||||
'host': 'host2'})
|
||||
comp1 = db.service_create(self.context, {'host': 'host1',
|
||||
'availability_zone': 'zone1',
|
||||
@ -447,7 +447,7 @@ class CloudTestCase(test.TestCase):
|
||||
|
||||
def test_terminate_instances(self):
|
||||
inst1 = db.instance_create(self.context, {'reservation_id': 'a',
|
||||
'image_id': 1,
|
||||
'image_ref': 1,
|
||||
'host': 'host1'})
|
||||
terminate_instances = self.cloud.terminate_instances
|
||||
# valid instance_id
|
||||
|
@ -84,7 +84,7 @@ class ComputeTestCase(test.TestCase):
|
||||
def _create_instance(self, params={}):
|
||||
"""Create a test instance"""
|
||||
inst = {}
|
||||
inst['image_id'] = 1
|
||||
inst['image_ref'] = 1
|
||||
inst['reservation_id'] = 'r-fakeres'
|
||||
inst['launch_time'] = '10'
|
||||
inst['user_id'] = self.user.id
|
||||
@ -150,7 +150,7 @@ class ComputeTestCase(test.TestCase):
|
||||
ref = self.compute_api.create(
|
||||
self.context,
|
||||
instance_type=instance_types.get_default_instance_type(),
|
||||
image_id=None,
|
||||
image_href=None,
|
||||
security_group=['testgroup'])
|
||||
try:
|
||||
self.assertEqual(len(db.security_group_get_by_instance(
|
||||
@ -168,7 +168,7 @@ class ComputeTestCase(test.TestCase):
|
||||
ref = self.compute_api.create(
|
||||
self.context,
|
||||
instance_type=instance_types.get_default_instance_type(),
|
||||
image_id=None,
|
||||
image_href=None,
|
||||
security_group=['testgroup'])
|
||||
try:
|
||||
db.instance_destroy(self.context, ref[0]['id'])
|
||||
@ -184,7 +184,7 @@ class ComputeTestCase(test.TestCase):
|
||||
ref = self.compute_api.create(
|
||||
self.context,
|
||||
instance_type=instance_types.get_default_instance_type(),
|
||||
image_id=None,
|
||||
image_href=None,
|
||||
security_group=['testgroup'])
|
||||
|
||||
try:
|
||||
|
@ -161,7 +161,7 @@ class LibvirtConnTestCase(test.TestCase):
|
||||
'vcpus': 2,
|
||||
'project_id': 'fake',
|
||||
'bridge': 'br101',
|
||||
'image_id': '123456',
|
||||
'image_ref': '123456',
|
||||
'instance_type_id': '5'} # m1.small
|
||||
|
||||
def lazy_load_library_exists(self):
|
||||
|
@ -223,7 +223,7 @@ class QuotaTestCase(test.TestCase):
|
||||
min_count=1,
|
||||
max_count=1,
|
||||
instance_type=inst_type,
|
||||
image_id=1)
|
||||
image_href=1)
|
||||
for instance_id in instance_ids:
|
||||
db.instance_destroy(self.context, instance_id)
|
||||
|
||||
@ -237,7 +237,7 @@ class QuotaTestCase(test.TestCase):
|
||||
min_count=1,
|
||||
max_count=1,
|
||||
instance_type=inst_type,
|
||||
image_id=1)
|
||||
image_href=1)
|
||||
for instance_id in instance_ids:
|
||||
db.instance_destroy(self.context, instance_id)
|
||||
|
||||
@ -295,7 +295,7 @@ class QuotaTestCase(test.TestCase):
|
||||
min_count=1,
|
||||
max_count=1,
|
||||
instance_type=inst_type,
|
||||
image_id='fake',
|
||||
image_href='fake',
|
||||
metadata=metadata)
|
||||
|
||||
def test_default_allowed_injected_files(self):
|
||||
@ -341,16 +341,18 @@ class QuotaTestCase(test.TestCase):
|
||||
self.assertEqual(limit, 23456)
|
||||
|
||||
def _create_with_injected_files(self, files):
|
||||
FLAGS.image_service = 'nova.image.fake.FakeImageService'
|
||||
api = compute.API(image_service=self.StubImageService())
|
||||
inst_type = instance_types.get_instance_type_by_name('m1.small')
|
||||
api.create(self.context, min_count=1, max_count=1,
|
||||
instance_type=inst_type, image_id='fake',
|
||||
instance_type=inst_type, image_href='3',
|
||||
injected_files=files)
|
||||
|
||||
def test_no_injected_files(self):
|
||||
FLAGS.image_service = 'nova.image.fake.FakeImageService'
|
||||
api = compute.API(image_service=self.StubImageService())
|
||||
inst_type = instance_types.get_instance_type_by_name('m1.small')
|
||||
api.create(self.context, instance_type=inst_type, image_id='fake')
|
||||
api.create(self.context, instance_type=inst_type, image_href='3')
|
||||
|
||||
def test_max_injected_files(self):
|
||||
files = []
|
||||
|
@ -55,8 +55,7 @@ class VMWareAPIVMTestCase(test.TestCase):
|
||||
vmwareapi_fake.reset()
|
||||
db_fakes.stub_out_db_instance_api(self.stubs)
|
||||
stubs.set_stubs(self.stubs)
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
glance_stubs.FakeGlance)
|
||||
glance_stubs.stubout_glance_client(self.stubs)
|
||||
self.conn = vmwareapi_conn.get_connection(False)
|
||||
|
||||
def _create_instance_in_the_db(self):
|
||||
@ -64,7 +63,7 @@ class VMWareAPIVMTestCase(test.TestCase):
|
||||
'id': 1,
|
||||
'project_id': self.project.id,
|
||||
'user_id': self.user.id,
|
||||
'image_id': "1",
|
||||
'image_ref': "1",
|
||||
'kernel_id': "1",
|
||||
'ramdisk_id': "1",
|
||||
'instance_type': 'm1.large',
|
||||
|
@ -79,7 +79,7 @@ class XenAPIVolumeTestCase(test.TestCase):
|
||||
self.values = {'id': 1,
|
||||
'project_id': 'fake',
|
||||
'user_id': 'fake',
|
||||
'image_id': 1,
|
||||
'image_ref': 1,
|
||||
'kernel_id': 2,
|
||||
'ramdisk_id': 3,
|
||||
'instance_type_id': '3', # m1.large
|
||||
@ -193,8 +193,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
stubs.stubout_is_vdi_pv(self.stubs)
|
||||
self.stubs.Set(VMOps, 'reset_network', reset_network)
|
||||
stubs.stub_out_vm_methods(self.stubs)
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
glance_stubs.FakeGlance)
|
||||
glance_stubs.stubout_glance_client(self.stubs)
|
||||
fake_utils.stub_out_utils_execute(self.stubs)
|
||||
self.context = context.RequestContext('fake', 'fake', False)
|
||||
self.conn = xenapi_conn.get_connection(False)
|
||||
@ -207,7 +206,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
'id': id,
|
||||
'project_id': proj,
|
||||
'user_id': user,
|
||||
'image_id': 1,
|
||||
'image_ref': 1,
|
||||
'kernel_id': 2,
|
||||
'ramdisk_id': 3,
|
||||
'instance_type_id': '3', # m1.large
|
||||
@ -351,14 +350,14 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
self.assertEquals(self.vm['HVM_boot_params'], {})
|
||||
self.assertEquals(self.vm['HVM_boot_policy'], '')
|
||||
|
||||
def _test_spawn(self, image_id, kernel_id, ramdisk_id,
|
||||
def _test_spawn(self, image_ref, kernel_id, ramdisk_id,
|
||||
instance_type_id="3", os_type="linux",
|
||||
instance_id=1, check_injection=False):
|
||||
stubs.stubout_loopingcall_start(self.stubs)
|
||||
values = {'id': instance_id,
|
||||
'project_id': self.project.id,
|
||||
'user_id': self.user.id,
|
||||
'image_id': image_id,
|
||||
'image_ref': image_ref,
|
||||
'kernel_id': kernel_id,
|
||||
'ramdisk_id': ramdisk_id,
|
||||
'instance_type_id': instance_type_id,
|
||||
@ -567,7 +566,7 @@ class XenAPIVMTestCase(test.TestCase):
|
||||
'id': 1,
|
||||
'project_id': self.project.id,
|
||||
'user_id': self.user.id,
|
||||
'image_id': 1,
|
||||
'image_ref': 1,
|
||||
'kernel_id': 2,
|
||||
'ramdisk_id': 3,
|
||||
'instance_type_id': '3', # m1.large
|
||||
@ -641,7 +640,7 @@ class XenAPIMigrateInstance(test.TestCase):
|
||||
self.values = {'id': 1,
|
||||
'project_id': self.project.id,
|
||||
'user_id': self.user.id,
|
||||
'image_id': 1,
|
||||
'image_ref': 1,
|
||||
'kernel_id': None,
|
||||
'ramdisk_id': None,
|
||||
'local_gb': 5,
|
||||
@ -652,8 +651,7 @@ class XenAPIMigrateInstance(test.TestCase):
|
||||
fake_utils.stub_out_utils_execute(self.stubs)
|
||||
stubs.stub_out_migration_methods(self.stubs)
|
||||
stubs.stubout_get_this_vm_uuid(self.stubs)
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
glance_stubs.FakeGlance)
|
||||
glance_stubs.stubout_glance_client(self.stubs)
|
||||
|
||||
def tearDown(self):
|
||||
super(XenAPIMigrateInstance, self).tearDown()
|
||||
@ -679,8 +677,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
"""Unit tests for code that detects the ImageType."""
|
||||
def setUp(self):
|
||||
super(XenAPIDetermineDiskImageTestCase, self).setUp()
|
||||
glance_stubs.stubout_glance_client(self.stubs,
|
||||
glance_stubs.FakeGlance)
|
||||
glance_stubs.stubout_glance_client(self.stubs)
|
||||
|
||||
class FakeInstance(object):
|
||||
pass
|
||||
@ -697,7 +694,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
def test_instance_disk(self):
|
||||
"""If a kernel is specified, the image type is DISK (aka machine)."""
|
||||
FLAGS.xenapi_image_service = 'objectstore'
|
||||
self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_MACHINE
|
||||
self.fake_instance.image_ref = glance_stubs.FakeGlance.IMAGE_MACHINE
|
||||
self.fake_instance.kernel_id = glance_stubs.FakeGlance.IMAGE_KERNEL
|
||||
self.assert_disk_type(vm_utils.ImageType.DISK)
|
||||
|
||||
@ -707,7 +704,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
DISK_RAW is assumed.
|
||||
"""
|
||||
FLAGS.xenapi_image_service = 'objectstore'
|
||||
self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_RAW
|
||||
self.fake_instance.image_ref = glance_stubs.FakeGlance.IMAGE_RAW
|
||||
self.fake_instance.kernel_id = None
|
||||
self.assert_disk_type(vm_utils.ImageType.DISK_RAW)
|
||||
|
||||
@ -717,7 +714,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
this case will be 'raw'.
|
||||
"""
|
||||
FLAGS.xenapi_image_service = 'glance'
|
||||
self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_RAW
|
||||
self.fake_instance.image_ref = glance_stubs.FakeGlance.IMAGE_RAW
|
||||
self.fake_instance.kernel_id = None
|
||||
self.assert_disk_type(vm_utils.ImageType.DISK_RAW)
|
||||
|
||||
@ -727,7 +724,7 @@ class XenAPIDetermineDiskImageTestCase(test.TestCase):
|
||||
this case will be 'vhd'.
|
||||
"""
|
||||
FLAGS.xenapi_image_service = 'glance'
|
||||
self.fake_instance.image_id = glance_stubs.FakeGlance.IMAGE_VHD
|
||||
self.fake_instance.image_ref = glance_stubs.FakeGlance.IMAGE_VHD
|
||||
self.fake_instance.kernel_id = None
|
||||
self.assert_disk_type(vm_utils.ImageType.DISK_VHD)
|
||||
|
||||
|
@ -61,7 +61,7 @@ def stub_out_db_instance_api(stubs):
|
||||
'name': values['name'],
|
||||
'id': values['id'],
|
||||
'reservation_id': utils.generate_uid('r'),
|
||||
'image_id': values['image_id'],
|
||||
'image_ref': values['image_ref'],
|
||||
'kernel_id': values['kernel_id'],
|
||||
'ramdisk_id': values['ramdisk_id'],
|
||||
'state_description': 'scheduling',
|
||||
|
@ -151,7 +151,7 @@ class HyperVConnection(driver.ComputeDriver):
|
||||
base_vhd_filename = os.path.join(FLAGS.instances_path,
|
||||
instance.name)
|
||||
vhdfile = "%s.vhd" % (base_vhd_filename)
|
||||
images.fetch(instance['image_id'], vhdfile, user, project)
|
||||
images.fetch(instance['image_ref'], vhdfile, user, project)
|
||||
|
||||
try:
|
||||
self._create_vm(instance)
|
||||
|
@ -23,6 +23,7 @@ Handling of VM disk images.
|
||||
|
||||
from nova import context
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
|
||||
@ -31,12 +32,12 @@ FLAGS = flags.FLAGS
|
||||
LOG = logging.getLogger('nova.virt.images')
|
||||
|
||||
|
||||
def fetch(image_id, path, _user, _project):
|
||||
def fetch(image_href, 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)
|
||||
(image_service, image_id) = nova.image.get_image_service(image_href)
|
||||
with open(path, "wb") as image_file:
|
||||
elevated = context.get_admin_context()
|
||||
metadata = image_service.get(elevated, image_id, image_file)
|
||||
|
@ -36,6 +36,7 @@ Supports KVM, LXC, QEMU, UML, and XEN.
|
||||
|
||||
"""
|
||||
|
||||
import hashlib
|
||||
import multiprocessing
|
||||
import os
|
||||
import random
|
||||
@ -57,6 +58,7 @@ from nova import context
|
||||
from nova import db
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
from nova import vnc
|
||||
@ -378,7 +380,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
virt_dom.detachDevice(xml)
|
||||
|
||||
@exception.wrap_exception
|
||||
def snapshot(self, instance, image_id):
|
||||
def snapshot(self, instance, image_href):
|
||||
"""Create snapshot from a running VM instance.
|
||||
|
||||
This command only works with qemu 0.14+, the qemu_img flag is
|
||||
@ -386,12 +388,15 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
to support this command.
|
||||
|
||||
"""
|
||||
image_service = utils.import_object(FLAGS.image_service)
|
||||
virt_dom = self._lookup_by_name(instance['name'])
|
||||
elevated = context.get_admin_context()
|
||||
|
||||
base = image_service.show(elevated, instance['image_id'])
|
||||
snapshot = image_service.show(elevated, image_id)
|
||||
(image_service, image_id) = nova.image.get_image_service(
|
||||
instance['image_ref'])
|
||||
base = image_service.show(elevated, image_id)
|
||||
(snapshot_image_service, snapshot_image_id) = \
|
||||
nova.image.get_image_service(image_href)
|
||||
snapshot = snapshot_image_service.show(elevated, snapshot_image_id)
|
||||
|
||||
metadata = {'disk_format': base['disk_format'],
|
||||
'container_format': base['container_format'],
|
||||
@ -441,7 +446,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
# Upload that image to the image service
|
||||
with open(out_path) as image_file:
|
||||
image_service.update(elevated,
|
||||
image_id,
|
||||
image_href,
|
||||
metadata,
|
||||
image_file)
|
||||
|
||||
@ -787,7 +792,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
project = manager.AuthManager().get_project(inst['project_id'])
|
||||
|
||||
if not disk_images:
|
||||
disk_images = {'image_id': inst['image_id'],
|
||||
disk_images = {'image_id': inst['image_ref'],
|
||||
'kernel_id': inst['kernel_id'],
|
||||
'ramdisk_id': inst['ramdisk_id']}
|
||||
|
||||
@ -808,7 +813,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
user=user,
|
||||
project=project)
|
||||
|
||||
root_fname = '%08x' % int(disk_images['image_id'])
|
||||
root_fname = hashlib.sha1(disk_images['image_id']).hexdigest()
|
||||
size = FLAGS.minimum_root_size
|
||||
|
||||
inst_type_id = inst['instance_type_id']
|
||||
@ -883,7 +888,7 @@ class LibvirtConnection(driver.ComputeDriver):
|
||||
|
||||
if key or net:
|
||||
inst_name = inst['name']
|
||||
img_id = inst.image_id
|
||||
img_id = inst.image_ref
|
||||
if key:
|
||||
LOG.info(_('instance %(inst_name)s: injecting key into'
|
||||
' image %(img_id)s') % locals())
|
||||
|
@ -195,7 +195,7 @@ class NWFilterFirewall(FirewallDriver):
|
||||
logging.info('ensuring static filters')
|
||||
self._ensure_static_filters()
|
||||
|
||||
if instance['image_id'] == str(FLAGS.vpn_image_id):
|
||||
if instance['image_ref'] == str(FLAGS.vpn_image_id):
|
||||
base_filter = 'nova-vpn'
|
||||
else:
|
||||
base_filter = 'nova-base'
|
||||
@ -336,7 +336,7 @@ class NWFilterFirewall(FirewallDriver):
|
||||
|
||||
def _create_network_filters(self, instance, network_info,
|
||||
instance_secgroup_filter_name):
|
||||
if instance['image_id'] == str(FLAGS.vpn_image_id):
|
||||
if instance['image_ref'] == str(FLAGS.vpn_image_id):
|
||||
base_filter = 'nova-vpn'
|
||||
else:
|
||||
base_filter = 'nova-base'
|
||||
|
@ -150,7 +150,7 @@ class VMWareVMOps(object):
|
||||
"""
|
||||
image_size, image_properties = \
|
||||
vmware_images.get_vmdk_size_and_properties(
|
||||
instance.image_id, instance)
|
||||
instance.image_ref, instance)
|
||||
vmdk_file_size_in_kb = int(image_size) / 1024
|
||||
os_type = image_properties.get("vmware_ostype", "otherGuest")
|
||||
adapter_type = image_properties.get("vmware_adaptertype",
|
||||
@ -265,23 +265,23 @@ class VMWareVMOps(object):
|
||||
|
||||
def _fetch_image_on_esx_datastore():
|
||||
"""Fetch image from Glance to ESX datastore."""
|
||||
LOG.debug(_("Downloading image file data %(image_id)s to the ESX "
|
||||
LOG.debug(_("Downloading image file data %(image_ref)s to the ESX "
|
||||
"data store %(data_store_name)s") %
|
||||
({'image_id': instance.image_id,
|
||||
({'image_ref': instance.image_ref,
|
||||
'data_store_name': data_store_name}))
|
||||
# Upload the -flat.vmdk file whose meta-data file we just created
|
||||
# above
|
||||
vmware_images.fetch_image(
|
||||
instance.image_id,
|
||||
instance.image_ref,
|
||||
instance,
|
||||
host=self._session._host_ip,
|
||||
data_center_name=self._get_datacenter_name_and_ref()[1],
|
||||
datastore_name=data_store_name,
|
||||
cookies=cookies,
|
||||
file_path=flat_uploaded_vmdk_name)
|
||||
LOG.debug(_("Downloaded image file data %(image_id)s to the ESX "
|
||||
LOG.debug(_("Downloaded image file data %(image_ref)s to the ESX "
|
||||
"data store %(data_store_name)s") %
|
||||
({'image_id': instance.image_id,
|
||||
({'image_ref': instance.image_ref,
|
||||
'data_store_name': data_store_name}))
|
||||
_fetch_image_on_esx_datastore()
|
||||
|
||||
|
@ -18,10 +18,9 @@
|
||||
Utility functions for Image transfer.
|
||||
"""
|
||||
|
||||
from glance import client
|
||||
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log as logging
|
||||
from nova.virt.vmwareapi import io_util
|
||||
from nova.virt.vmwareapi import read_write_util
|
||||
@ -117,8 +116,8 @@ def upload_image(image, instance, **kwargs):
|
||||
def _get_glance_image(image, instance, **kwargs):
|
||||
"""Download image from the glance image server."""
|
||||
LOG.debug(_("Downloading image %s from glance image server") % image)
|
||||
glance_client = client.Client(FLAGS.glance_host, FLAGS.glance_port)
|
||||
metadata, read_iter = glance_client.get_image(image)
|
||||
(glance_client, image_id) = nova.image.get_glance_client(image)
|
||||
metadata, read_iter = glance_client.get_image(image_id)
|
||||
read_file_handle = read_write_util.GlanceFileRead(read_iter)
|
||||
file_size = int(metadata['size'])
|
||||
write_file_handle = read_write_util.VMWareHTTPWriteFile(
|
||||
@ -153,7 +152,7 @@ def _put_glance_image(image, instance, **kwargs):
|
||||
kwargs.get("cookies"),
|
||||
kwargs.get("file_path"))
|
||||
file_size = read_file_handle.get_size()
|
||||
glance_client = client.Client(FLAGS.glance_host, FLAGS.glance_port)
|
||||
(glance_client, image_id) = nova.image.get_glance_client(image)
|
||||
# The properties and other fields that we need to set for the image.
|
||||
image_metadata = {"is_public": True,
|
||||
"disk_format": "vmdk",
|
||||
@ -165,7 +164,7 @@ def _put_glance_image(image, instance, **kwargs):
|
||||
"vmware_image_version":
|
||||
kwargs.get("image_version")}}
|
||||
start_transfer(read_file_handle, file_size, glance_client=glance_client,
|
||||
image_id=image, image_meta=image_metadata)
|
||||
image_id=image_id, image_meta=image_metadata)
|
||||
LOG.debug(_("Uploaded image %s to the Glance image server") % image)
|
||||
|
||||
|
||||
@ -188,9 +187,8 @@ def get_vmdk_size_and_properties(image, instance):
|
||||
|
||||
LOG.debug(_("Getting image size for the image %s") % image)
|
||||
if FLAGS.image_service == "nova.image.glance.GlanceImageService":
|
||||
glance_client = client.Client(FLAGS.glance_host,
|
||||
FLAGS.glance_port)
|
||||
meta_data = glance_client.get_image_meta(image)
|
||||
(glance_client, image_id) = nova.image.get_glance_client(image)
|
||||
meta_data = glance_client.get_image_meta(image_id)
|
||||
size, properties = meta_data["size"], meta_data["properties"]
|
||||
elif FLAGS.image_service == "nova.image.s3.S3ImageService":
|
||||
raise NotImplementedError
|
||||
|
@ -32,6 +32,7 @@ from xml.dom import minidom
|
||||
import glance.client
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
from nova.auth.manager import AuthManager
|
||||
@ -455,8 +456,8 @@ class VMHelper(HelperBase):
|
||||
# DISK restores
|
||||
sr_ref = safe_find_sr(session)
|
||||
|
||||
client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port)
|
||||
meta, image_file = client.get_image(image)
|
||||
glance_client, image_id = nova.image.get_glance_client(image)
|
||||
meta, image_file = glance_client.get_image(image_id)
|
||||
virtual_size = int(meta['size'])
|
||||
vdi_size = virtual_size
|
||||
LOG.debug(_("Size for image %(image)s:%(virtual_size)d") % locals())
|
||||
@ -515,10 +516,10 @@ class VMHelper(HelperBase):
|
||||
ImageType.DISK_RAW: 'DISK_RAW',
|
||||
ImageType.DISK_VHD: 'DISK_VHD'}
|
||||
disk_format = pretty_format[image_type]
|
||||
image_id = instance.image_id
|
||||
image_ref = instance.image_ref
|
||||
instance_id = instance.id
|
||||
LOG.debug(_("Detected %(disk_format)s format for image "
|
||||
"%(image_id)s, instance %(instance_id)s") % locals())
|
||||
"%(image_ref)s, instance %(instance_id)s") % locals())
|
||||
|
||||
def determine_from_glance():
|
||||
glance_disk_format2nova_type = {
|
||||
@ -527,8 +528,9 @@ class VMHelper(HelperBase):
|
||||
'ari': ImageType.KERNEL_RAMDISK,
|
||||
'raw': ImageType.DISK_RAW,
|
||||
'vhd': ImageType.DISK_VHD}
|
||||
client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port)
|
||||
meta = client.get_image_meta(instance.image_id)
|
||||
image_ref = instance.image_ref
|
||||
glance_client, image_id = nova.image.get_glance_client(image_ref)
|
||||
meta = glance_client.get_image_meta(image_id)
|
||||
disk_format = meta['disk_format']
|
||||
try:
|
||||
return glance_disk_format2nova_type[disk_format]
|
||||
|
@ -111,7 +111,7 @@ class VMOps(object):
|
||||
project = AuthManager().get_project(instance.project_id)
|
||||
disk_image_type = VMHelper.determine_disk_image_type(instance)
|
||||
vdis = VMHelper.fetch_image(self._session,
|
||||
instance.id, instance.image_id, user, project,
|
||||
instance.id, instance.image_ref, user, project,
|
||||
disk_image_type)
|
||||
return vdis
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user