removing local image service
This commit is contained in:
@@ -120,6 +120,14 @@ class _FakeImageService(service.BaseImageService):
|
||||
image_id, self.images)
|
||||
raise exception.ImageNotFound(image_id=image_id)
|
||||
|
||||
def show_by_name(self, context, name):
|
||||
"""Returns a dict containing image data for the given name."""
|
||||
images = copy.deepcopy(self.images.values())
|
||||
for image in images:
|
||||
if name == image.get('name'):
|
||||
return image
|
||||
raise exception.ImageNotFound(image_id=name)
|
||||
|
||||
def create(self, context, metadata, data=None):
|
||||
"""Store the image data and return the new image id.
|
||||
|
||||
|
||||
@@ -1,167 +0,0 @@
|
||||
# vim: tabstop=4 shiftwidth=4 softtabstop=4
|
||||
|
||||
# Copyright 2010 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.
|
||||
|
||||
import json
|
||||
import os.path
|
||||
import random
|
||||
import shutil
|
||||
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
from nova import log as logging
|
||||
from nova import utils
|
||||
from nova.image import service
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
flags.DEFINE_string('images_path', '$state_path/images',
|
||||
'path to decrypted images')
|
||||
|
||||
|
||||
LOG = logging.getLogger('nova.image.local')
|
||||
|
||||
|
||||
class LocalImageService(service.BaseImageService):
|
||||
"""Image service storing images to local disk.
|
||||
|
||||
It assumes that image_ids are integers.
|
||||
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
self._path = FLAGS.images_path
|
||||
|
||||
def _path_to(self, image_id, fname='info.json'):
|
||||
if fname:
|
||||
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."""
|
||||
images = []
|
||||
for image_dir in os.listdir(self._path):
|
||||
try:
|
||||
unhexed_image_id = int(image_dir, 16)
|
||||
except ValueError:
|
||||
LOG.error(_('%s is not in correct directory naming format')
|
||||
% image_dir)
|
||||
else:
|
||||
images.append(unhexed_image_id)
|
||||
return images
|
||||
|
||||
def index(self, context, filters=None, marker=None, limit=None):
|
||||
# TODO(blamar): Make use of filters, marker, and limit
|
||||
filtered = []
|
||||
image_metas = self.detail(context)
|
||||
for image_meta in image_metas:
|
||||
meta = utils.subset_dict(image_meta, ('id', 'name'))
|
||||
filtered.append(meta)
|
||||
return filtered
|
||||
|
||||
def detail(self, context, filters=None, marker=None, limit=None):
|
||||
# TODO(blamar): Make use of filters, marker, and limit
|
||||
images = []
|
||||
for image_id in self._ids():
|
||||
try:
|
||||
image = self.show(context, image_id)
|
||||
images.append(image)
|
||||
except exception.NotFound:
|
||||
continue
|
||||
return images
|
||||
|
||||
def show(self, context, image_id):
|
||||
try:
|
||||
with open(self._path_to(image_id)) as metadata_file:
|
||||
image_meta = json.load(metadata_file)
|
||||
if not self._is_image_available(context, image_meta):
|
||||
raise exception.ImageNotFound(image_id=image_id)
|
||||
return image_meta
|
||||
except (IOError, ValueError):
|
||||
raise exception.ImageNotFound(image_id=image_id)
|
||||
|
||||
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 is None:
|
||||
raise exception.ImageNotFound(image_id=name)
|
||||
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.ImageNotFound(image_id=image_id)
|
||||
return metadata
|
||||
|
||||
def create(self, context, metadata, data=None):
|
||||
"""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._store(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."""
|
||||
# NOTE(vish): show is to check if image is available
|
||||
self.show(context, image_id)
|
||||
return self._store(context, image_id, metadata, data)
|
||||
|
||||
def _store(self, context, image_id, metadata, data=None):
|
||||
metadata['id'] = image_id
|
||||
try:
|
||||
if data:
|
||||
location = self._path_to(image_id, 'image')
|
||||
with open(location, 'w') as image_file:
|
||||
shutil.copyfileobj(data, image_file)
|
||||
# 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.ImageNotFound(image_id=image_id)
|
||||
return metadata
|
||||
|
||||
def delete(self, context, image_id):
|
||||
"""Delete the given image.
|
||||
|
||||
:raises: ImageNotFound if the image does not exist.
|
||||
|
||||
"""
|
||||
# NOTE(vish): show is to check if image is available
|
||||
self.show(context, image_id)
|
||||
try:
|
||||
shutil.rmtree(self._path_to(image_id, None))
|
||||
except (IOError, ValueError):
|
||||
raise exception.ImageNotFound(image_id=image_id)
|
||||
|
||||
def delete_all(self):
|
||||
"""Clears out all images in local directory."""
|
||||
for image_id in self._ids():
|
||||
shutil.rmtree(self._path_to(image_id, None))
|
||||
@@ -39,7 +39,6 @@ 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
|
||||
from nova.tests import fake_flags
|
||||
from nova.wsgi import Router
|
||||
|
||||
@@ -135,36 +135,6 @@ class _BaseImageServiceTests(test.TestCase):
|
||||
return fixture
|
||||
|
||||
|
||||
class LocalImageServiceTest(_BaseImageServiceTests):
|
||||
|
||||
"""Tests the local image service"""
|
||||
|
||||
def setUp(self):
|
||||
super(LocalImageServiceTest, self).setUp()
|
||||
self.tempdir = tempfile.mkdtemp()
|
||||
self.flags(images_path=self.tempdir)
|
||||
self.stubs = stubout.StubOutForTesting()
|
||||
service_class = 'nova.image.local.LocalImageService'
|
||||
self.service = utils.import_object(service_class)
|
||||
self.context = context.RequestContext(None, None)
|
||||
|
||||
def tearDown(self):
|
||||
shutil.rmtree(self.tempdir)
|
||||
self.stubs.UnsetAll()
|
||||
super(LocalImageServiceTest, self).tearDown()
|
||||
|
||||
def test_get_all_ids_with_incorrect_directory_formats(self):
|
||||
# create some old-style image directories (starting with 'ami-')
|
||||
for x in [1, 2, 3]:
|
||||
tempfile.mkstemp(prefix='ami-', dir=self.tempdir)
|
||||
# create some valid image directories names
|
||||
for x in ["1485baed", "1a60f0ee", "3123a73d"]:
|
||||
os.makedirs(os.path.join(self.tempdir, x))
|
||||
found_image_ids = self.service._ids()
|
||||
self.assertEqual(True, isinstance(found_image_ids, list))
|
||||
self.assertEqual(3, len(found_image_ids), len(found_image_ids))
|
||||
|
||||
|
||||
class GlanceImageServiceTest(_BaseImageServiceTests):
|
||||
|
||||
"""Tests the Glance image service, in particular that metadata translation
|
||||
|
||||
@@ -32,7 +32,7 @@ flags.DECLARE('fake_network', 'nova.network.manager')
|
||||
FLAGS['network_size'].SetDefault(8)
|
||||
FLAGS['num_networks'].SetDefault(2)
|
||||
FLAGS['fake_network'].SetDefault(True)
|
||||
FLAGS['image_service'].SetDefault('nova.image.local.LocalImageService')
|
||||
FLAGS['image_service'].SetDefault('nova.image.fake.FakeImageService')
|
||||
flags.DECLARE('num_shelves', 'nova.volume.driver')
|
||||
flags.DECLARE('blades_per_shelf', 'nova.volume.driver')
|
||||
flags.DECLARE('iscsi_num_targets', 'nova.volume.driver')
|
||||
|
||||
@@ -35,7 +35,7 @@ from nova import utils
|
||||
from nova.auth import manager
|
||||
from nova.api.ec2 import cloud
|
||||
from nova.api.ec2 import ec2utils
|
||||
from nova.image import local
|
||||
from nova.image import fake
|
||||
|
||||
|
||||
FLAGS = flags.FLAGS
|
||||
@@ -69,8 +69,8 @@ class CloudTestCase(test.TestCase):
|
||||
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
|
||||
'type': 'machine', 'image_state': 'available'}}
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show)
|
||||
self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
|
||||
self.stubs.Set(fake._FakeImageService, 'show', fake_show)
|
||||
self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
|
||||
|
||||
# NOTE(vish): set up a manual wait so rpc.cast has a chance to finish
|
||||
rpc_cast = rpc.cast
|
||||
@@ -291,7 +291,7 @@ class CloudTestCase(test.TestCase):
|
||||
def fake_show_none(meh, context, id):
|
||||
raise exception.ImageNotFound(image_id='bad_image_id')
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'detail', fake_detail)
|
||||
self.stubs.Set(fake._FakeImageService, 'detail', fake_detail)
|
||||
# list all
|
||||
result1 = describe_images(self.context)
|
||||
result1 = result1['imagesSet'][0]
|
||||
@@ -305,8 +305,8 @@ class CloudTestCase(test.TestCase):
|
||||
self.assertEqual(2, len(result3['imagesSet']))
|
||||
# provide an non-existing image_id
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show_none)
|
||||
self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show_none)
|
||||
self.stubs.Set(fake._FakeImageService, 'show', fake_show_none)
|
||||
self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show_none)
|
||||
self.assertRaises(exception.ImageNotFound, describe_images,
|
||||
self.context, ['ami-fake'])
|
||||
|
||||
@@ -317,8 +317,8 @@ class CloudTestCase(test.TestCase):
|
||||
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1,
|
||||
'type': 'machine'}, 'is_public': True}
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show)
|
||||
self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
|
||||
self.stubs.Set(fake._FakeImageService, 'show', fake_show)
|
||||
self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
|
||||
result = describe_image_attribute(self.context, 'ami-00000001',
|
||||
'launchPermission')
|
||||
self.assertEqual([{'group': 'all'}], result['launchPermission'])
|
||||
@@ -333,9 +333,9 @@ class CloudTestCase(test.TestCase):
|
||||
def fake_update(meh, context, image_id, metadata, data=None):
|
||||
return metadata
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show)
|
||||
self.stubs.Set(local.LocalImageService, 'show_by_name', fake_show)
|
||||
self.stubs.Set(local.LocalImageService, 'update', fake_update)
|
||||
self.stubs.Set(fake._FakeImageService, 'show', fake_show)
|
||||
self.stubs.Set(fake._FakeImageService, 'show_by_name', fake_show)
|
||||
self.stubs.Set(fake._FakeImageService, 'update', fake_update)
|
||||
result = modify_image_attribute(self.context, 'ami-00000001',
|
||||
'launchPermission', 'add',
|
||||
user_group=['all'])
|
||||
@@ -347,7 +347,7 @@ class CloudTestCase(test.TestCase):
|
||||
def fake_delete(self, context, id):
|
||||
return None
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'delete', fake_delete)
|
||||
self.stubs.Set(fake._FakeImageService, 'delete', fake_delete)
|
||||
# valid image
|
||||
result = deregister_image(self.context, 'ami-00000001')
|
||||
self.assertEqual(result['imageId'], 'ami-00000001')
|
||||
@@ -357,7 +357,7 @@ class CloudTestCase(test.TestCase):
|
||||
def fake_detail_empty(self, context):
|
||||
return []
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'detail', fake_detail_empty)
|
||||
self.stubs.Set(fake._FakeImageService, 'detail', fake_detail_empty)
|
||||
self.assertRaises(exception.ImageNotFound, deregister_image,
|
||||
self.context, 'ami-bad001')
|
||||
|
||||
@@ -468,7 +468,7 @@ class CloudTestCase(test.TestCase):
|
||||
'type': 'machine'}}
|
||||
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show_no_state)
|
||||
self.stubs.Set(fake._FakeImageService, 'show', fake_show_no_state)
|
||||
self.assertRaises(exception.ApiError, run_instances,
|
||||
self.context, **kwargs)
|
||||
|
||||
@@ -483,7 +483,7 @@ class CloudTestCase(test.TestCase):
|
||||
'type': 'machine', 'image_state': 'decrypting'}}
|
||||
|
||||
self.stubs.UnsetAll()
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show_decrypt)
|
||||
self.stubs.Set(fake._FakeImageService, 'show', fake_show_decrypt)
|
||||
self.assertRaises(exception.ApiError, run_instances,
|
||||
self.context, **kwargs)
|
||||
|
||||
|
||||
@@ -22,21 +22,21 @@ Tests For Compute
|
||||
import mox
|
||||
import stubout
|
||||
|
||||
from nova.auth import manager
|
||||
from nova import compute
|
||||
from nova.compute import instance_types
|
||||
from nova.compute import manager as compute_manager
|
||||
from nova.compute import power_state
|
||||
from nova import context
|
||||
from nova import db
|
||||
from nova.db.sqlalchemy import models
|
||||
from nova import exception
|
||||
from nova import flags
|
||||
import nova.image.fake
|
||||
from nova import log as logging
|
||||
from nova import rpc
|
||||
from nova import test
|
||||
from nova import utils
|
||||
from nova.auth import manager
|
||||
from nova.compute import instance_types
|
||||
from nova.compute import manager as compute_manager
|
||||
from nova.compute import power_state
|
||||
from nova.db.sqlalchemy import models
|
||||
from nova.image import local
|
||||
|
||||
LOG = logging.getLogger('nova.tests.compute')
|
||||
FLAGS = flags.FLAGS
|
||||
@@ -73,7 +73,7 @@ class ComputeTestCase(test.TestCase):
|
||||
def fake_show(meh, context, id):
|
||||
return {'id': 1, 'properties': {'kernel_id': 1, 'ramdisk_id': 1}}
|
||||
|
||||
self.stubs.Set(local.LocalImageService, 'show', fake_show)
|
||||
self.stubs.Set(nova.image.fake._FakeImageService, 'show', fake_show)
|
||||
|
||||
def tearDown(self):
|
||||
self.manager.delete_user(self.user)
|
||||
|
||||
Reference in New Issue
Block a user