~ubuntu-cloud-archive/ubuntu/precise/nova/trunk

« back to all changes in this revision

Viewing changes to nova/tests/image/fake.py

  • Committer: Package Import Robot
  • Author(s): Chuck Short, Adam Gandelman, Chuck Short
  • Date: 2012-07-06 10:18:33 UTC
  • mfrom: (1.1.58)
  • Revision ID: package-import@ubuntu.com-20120706101833-wp2nv392mpe9re8p
Tags: 2012.2~f2-0ubuntu1
[ Adam Gandelman ]
* Use new rootwrap configuration structure:
  - debian/nova-{compute, network, volume}.{pyinstall, pyremove}: Dropped.
  - debian/nova-common.dirs: Add /etc/nova/rootwrap.d/.
  - debian/nova-common.install: Install /etc/nova/rootwrap.conf.
  - debian/debian/nova.conf: Reference rootwrap.conf in calls to
    nova-rootwrap.
  - debian/nova-{compute, network, volume}.install: Install corresponding
    filter in /etc/nova/rootwrap.d/
* debian/rules: Install logging_sample.conf to /etc/nova/logging.conf
  as part of nova-common.
* debian/pydist-overrides: Add setuptools-git.
* debian/control: Add python-setuptools-git as a Build-Depends.
* debian/rules: Do not remove nova.egg-info during auto_clean.  Now that
  upstream has moved to setuptools-git, doing so results in missing files
  from built package.

[ Chuck Short ]
* New upstream release.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# vim: tabstop=4 shiftwidth=4 softtabstop=4
 
2
 
 
3
# Copyright 2011 Justin Santa Barbara
 
4
# Copyright 2012 OpenStack LLC
 
5
# All Rights Reserved.
 
6
#
 
7
#    Licensed under the Apache License, Version 2.0 (the "License"); you may
 
8
#    not use this file except in compliance with the License. You may obtain
 
9
#    a copy of the License at
 
10
#
 
11
#         http://www.apache.org/licenses/LICENSE-2.0
 
12
#
 
13
#    Unless required by applicable law or agreed to in writing, software
 
14
#    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 
15
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 
16
#    License for the specific language governing permissions and limitations
 
17
#    under the License.
 
18
 
 
19
"""Implementation of a fake image service"""
 
20
 
 
21
import copy
 
22
import datetime
 
23
 
 
24
from nova import exception
 
25
from nova import flags
 
26
import nova.image.glance
 
27
from nova.openstack.common import log as logging
 
28
from nova import utils
 
29
 
 
30
 
 
31
LOG = logging.getLogger(__name__)
 
32
 
 
33
 
 
34
FLAGS = flags.FLAGS
 
35
 
 
36
 
 
37
class _FakeImageService(object):
 
38
    """Mock (fake) image service for unit testing."""
 
39
 
 
40
    def __init__(self):
 
41
        self.images = {}
 
42
        # NOTE(justinsb): The OpenStack API can't upload an image?
 
43
        # So, make sure we've got one..
 
44
        timestamp = datetime.datetime(2011, 01, 01, 01, 02, 03)
 
45
 
 
46
        image1 = {'id': '155d900f-4e14-4e4c-a73d-069cbf4541e6',
 
47
                 'name': 'fakeimage123456',
 
48
                 'created_at': timestamp,
 
49
                 'updated_at': timestamp,
 
50
                 'deleted_at': None,
 
51
                 'deleted': False,
 
52
                 'status': 'active',
 
53
                 'is_public': False,
 
54
                 'container_format': 'raw',
 
55
                 'disk_format': 'raw',
 
56
                 'properties': {'kernel_id': FLAGS.null_kernel,
 
57
                                'ramdisk_id': FLAGS.null_kernel,
 
58
                                'architecture': 'x86_64'}}
 
59
 
 
60
        image2 = {'id': 'a2459075-d96c-40d5-893e-577ff92e721c',
 
61
                 'name': 'fakeimage123456',
 
62
                 'created_at': timestamp,
 
63
                 'updated_at': timestamp,
 
64
                 'deleted_at': None,
 
65
                 'deleted': False,
 
66
                 'status': 'active',
 
67
                 'is_public': True,
 
68
                 'container_format': 'ami',
 
69
                 'disk_format': 'ami',
 
70
                 'properties': {'kernel_id': FLAGS.null_kernel,
 
71
                                'ramdisk_id': FLAGS.null_kernel}}
 
72
 
 
73
        image3 = {'id': '76fa36fc-c930-4bf3-8c8a-ea2a2420deb6',
 
74
                 'name': 'fakeimage123456',
 
75
                 'created_at': timestamp,
 
76
                 'updated_at': timestamp,
 
77
                 'deleted_at': None,
 
78
                 'deleted': False,
 
79
                 'status': 'active',
 
80
                 'is_public': True,
 
81
                 'container_format': None,
 
82
                 'disk_format': None,
 
83
                 'properties': {'kernel_id': FLAGS.null_kernel,
 
84
                                'ramdisk_id': FLAGS.null_kernel}}
 
85
 
 
86
        image4 = {'id': 'cedef40a-ed67-4d10-800e-17455edce175',
 
87
                 'name': 'fakeimage123456',
 
88
                 'created_at': timestamp,
 
89
                 'updated_at': timestamp,
 
90
                 'deleted_at': None,
 
91
                 'deleted': False,
 
92
                 'status': 'active',
 
93
                 'is_public': True,
 
94
                 'container_format': 'ami',
 
95
                 'disk_format': 'ami',
 
96
                 'properties': {'kernel_id': FLAGS.null_kernel,
 
97
                                'ramdisk_id': FLAGS.null_kernel}}
 
98
 
 
99
        image5 = {'id': 'c905cedb-7281-47e4-8a62-f26bc5fc4c77',
 
100
                 'name': 'fakeimage123456',
 
101
                 'created_at': timestamp,
 
102
                 'updated_at': timestamp,
 
103
                 'deleted_at': None,
 
104
                 'deleted': False,
 
105
                 'status': 'active',
 
106
                 'is_public': True,
 
107
                 'container_format': 'ami',
 
108
                 'disk_format': 'ami',
 
109
                 'properties': {'kernel_id':
 
110
                                    '155d900f-4e14-4e4c-a73d-069cbf4541e6',
 
111
                                'ramdisk_id': None}}
 
112
 
 
113
        image6 = {'id': 'a440c04b-79fa-479c-bed1-0b816eaec379',
 
114
                 'name': 'fakeimage6',
 
115
                 'created_at': timestamp,
 
116
                 'updated_at': timestamp,
 
117
                 'deleted_at': None,
 
118
                 'deleted': False,
 
119
                 'status': 'active',
 
120
                 'is_public': False,
 
121
                 'container_format': 'ova',
 
122
                 'disk_format': 'vhd',
 
123
                 'properties': {'kernel_id': FLAGS.null_kernel,
 
124
                                'ramdisk_id': FLAGS.null_kernel,
 
125
                                'architecture': 'x86_64',
 
126
                                'auto_disk_config': 'False'}}
 
127
 
 
128
        image7 = {'id': '70a599e0-31e7-49b7-b260-868f441e862b',
 
129
                 'name': 'fakeimage7',
 
130
                 'created_at': timestamp,
 
131
                 'updated_at': timestamp,
 
132
                 'deleted_at': None,
 
133
                 'deleted': False,
 
134
                 'status': 'active',
 
135
                 'is_public': False,
 
136
                 'container_format': 'ova',
 
137
                 'disk_format': 'vhd',
 
138
                 'properties': {'kernel_id': FLAGS.null_kernel,
 
139
                                'ramdisk_id': FLAGS.null_kernel,
 
140
                                'architecture': 'x86_64',
 
141
                                'auto_disk_config': 'True'}}
 
142
 
 
143
        self.create(None, image1)
 
144
        self.create(None, image2)
 
145
        self.create(None, image3)
 
146
        self.create(None, image4)
 
147
        self.create(None, image5)
 
148
        self.create(None, image6)
 
149
        self.create(None, image7)
 
150
        self._imagedata = {}
 
151
        super(_FakeImageService, self).__init__()
 
152
 
 
153
    #TODO(bcwaldon): implement optional kwargs such as limit, sort_dir
 
154
    def detail(self, context, **kwargs):
 
155
        """Return list of detailed image information."""
 
156
        return copy.deepcopy(self.images.values())
 
157
 
 
158
    def download(self, context, image_id, data):
 
159
        self.show(context, image_id)
 
160
        data.write(self._imagedata.get(image_id, ''))
 
161
 
 
162
    def show(self, context, image_id):
 
163
        """Get data about specified image.
 
164
 
 
165
        Returns a dict containing image data for the given opaque image id.
 
166
 
 
167
        """
 
168
        image = self.images.get(str(image_id))
 
169
        if image:
 
170
            return copy.deepcopy(image)
 
171
        LOG.warn('Unable to find image id %s.  Have images: %s',
 
172
                 image_id, self.images)
 
173
        raise exception.ImageNotFound(image_id=image_id)
 
174
 
 
175
    def create(self, context, metadata, data=None):
 
176
        """Store the image data and return the new image id.
 
177
 
 
178
        :raises: Duplicate if the image already exist.
 
179
 
 
180
        """
 
181
        image_id = str(metadata.get('id', utils.gen_uuid()))
 
182
        metadata['id'] = image_id
 
183
        if image_id in self.images:
 
184
            raise exception.Duplicate()
 
185
        self.images[image_id] = copy.deepcopy(metadata)
 
186
        if data:
 
187
            self._imagedata[image_id] = data.read()
 
188
        return self.images[image_id]
 
189
 
 
190
    def update(self, context, image_id, metadata, data=None,
 
191
               headers=None):
 
192
        """Replace the contents of the given image with the new data.
 
193
 
 
194
        :raises: ImageNotFound if the image does not exist.
 
195
 
 
196
        """
 
197
        if not self.images.get(image_id):
 
198
            raise exception.ImageNotFound(image_id=image_id)
 
199
        try:
 
200
            purge = headers['x-glance-registry-purge-props']
 
201
        except Exception:
 
202
            purge = True
 
203
        if purge:
 
204
            self.images[image_id] = copy.deepcopy(metadata)
 
205
        else:
 
206
            image = self.images[image_id]
 
207
            try:
 
208
                image['properties'].update(metadata.pop('properties'))
 
209
            except Exception:
 
210
                pass
 
211
            image.update(metadata)
 
212
        return self.images[image_id]
 
213
 
 
214
    def delete(self, context, image_id):
 
215
        """Delete the given image.
 
216
 
 
217
        :raises: ImageNotFound if the image does not exist.
 
218
 
 
219
        """
 
220
        removed = self.images.pop(image_id, None)
 
221
        if not removed:
 
222
            raise exception.ImageNotFound(image_id=image_id)
 
223
 
 
224
    def delete_all(self):
 
225
        """Clears out all images."""
 
226
        self.images.clear()
 
227
 
 
228
_fakeImageService = _FakeImageService()
 
229
 
 
230
 
 
231
def FakeImageService():
 
232
    return _fakeImageService
 
233
 
 
234
 
 
235
def FakeImageService_reset():
 
236
    global _fakeImageService
 
237
    _fakeImageService = _FakeImageService()
 
238
 
 
239
 
 
240
def stub_out_image_service(stubs):
 
241
    def fake_get_remote_image_service(context, image_href):
 
242
        return (FakeImageService(), image_href)
 
243
    stubs.Set(nova.image.glance, 'get_remote_image_service',
 
244
              lambda x, y: (FakeImageService(), y))
 
245
    stubs.Set(nova.image.glance, 'get_default_image_service',
 
246
              lambda: FakeImageService())