~ubuntu-branches/ubuntu/quantal/nova/quantal-proposed

« back to all changes in this revision

Viewing changes to nova/image/glance.py

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2011-01-21 11:48:06 UTC
  • mto: This revision was merged to the branch mainline in revision 9.
  • Revision ID: james.westby@ubuntu.com-20110121114806-v8fvnnl6az4m4ohv
Tags: upstream-2011.1~bzr597
ImportĀ upstreamĀ versionĀ 2011.1~bzr597

Show diffs side-by-side

added added

removed removed

Lines of Context:
14
14
#    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
15
15
#    License for the specific language governing permissions and limitations
16
16
#    under the License.
17
 
 
18
17
"""Implementation of an image service that uses Glance as the backend"""
19
18
 
 
19
from __future__ import absolute_import
20
20
import httplib
21
21
import json
22
 
import logging
23
22
import urlparse
24
23
 
25
 
import webob.exc
26
 
 
 
24
from nova import exception
 
25
from nova import flags
 
26
from nova import log as logging
27
27
from nova import utils
28
 
from nova import flags
29
 
from nova import exception
30
 
import nova.image.service
 
28
from nova.image import service
 
29
 
 
30
 
 
31
LOG = logging.getLogger('nova.image.glance')
31
32
 
32
33
FLAGS = flags.FLAGS
33
34
 
34
 
 
35
 
flags.DEFINE_string('glance_teller_address', 'http://127.0.0.1',
36
 
                    'IP address or URL where Glance\'s Teller service resides')
37
 
flags.DEFINE_string('glance_teller_port', '9191',
38
 
                    'Port for Glance\'s Teller service')
39
 
flags.DEFINE_string('glance_parallax_address', 'http://127.0.0.1',
40
 
                    'IP address or URL where Glance\'s Parallax service '
41
 
                    'resides')
42
 
flags.DEFINE_string('glance_parallax_port', '9292',
43
 
                    'Port for Glance\'s Parallax service')
44
 
 
45
 
 
46
 
class TellerClient(object):
47
 
 
48
 
    def __init__(self):
49
 
        self.address = FLAGS.glance_teller_address
50
 
        self.port = FLAGS.glance_teller_port
51
 
        url = urlparse.urlparse(self.address)
52
 
        self.netloc = url.netloc
53
 
        self.connection_type = {'http': httplib.HTTPConnection,
54
 
                                'https': httplib.HTTPSConnection}[url.scheme]
55
 
 
56
 
 
57
 
class ParallaxClient(object):
58
 
 
59
 
    def __init__(self):
60
 
        self.address = FLAGS.glance_parallax_address
61
 
        self.port = FLAGS.glance_parallax_port
62
 
        url = urlparse.urlparse(self.address)
63
 
        self.netloc = url.netloc
64
 
        self.connection_type = {'http': httplib.HTTPConnection,
65
 
                                'https': httplib.HTTPSConnection}[url.scheme]
66
 
 
67
 
    def get_image_index(self):
68
 
        """
69
 
        Returns a list of image id/name mappings from Parallax
70
 
        """
71
 
        try:
72
 
            c = self.connection_type(self.netloc, self.port)
73
 
            c.request("GET", "images")
74
 
            res = c.getresponse()
75
 
            if res.status == 200:
76
 
                # Parallax returns a JSONified dict(images=image_list)
77
 
                data = json.loads(res.read())['images']
78
 
                return data
79
 
            else:
80
 
                logging.warn("Parallax returned HTTP error %d from "
81
 
                             "request for /images", res.status_int)
82
 
                return []
83
 
        finally:
84
 
            c.close()
85
 
 
86
 
    def get_image_details(self):
87
 
        """
88
 
        Returns a list of detailed image data mappings from Parallax
89
 
        """
90
 
        try:
91
 
            c = self.connection_type(self.netloc, self.port)
92
 
            c.request("GET", "images/detail")
93
 
            res = c.getresponse()
94
 
            if res.status == 200:
95
 
                # Parallax returns a JSONified dict(images=image_list)
96
 
                data = json.loads(res.read())['images']
97
 
                return data
98
 
            else:
99
 
                logging.warn("Parallax returned HTTP error %d from "
100
 
                             "request for /images/detail", res.status_int)
101
 
                return []
102
 
        finally:
103
 
            c.close()
104
 
 
105
 
    def get_image_metadata(self, image_id):
106
 
        """
107
 
        Returns a mapping of image metadata from Parallax
108
 
        """
109
 
        try:
110
 
            c = self.connection_type(self.netloc, self.port)
111
 
            c.request("GET", "images/%s" % image_id)
112
 
            res = c.getresponse()
113
 
            if res.status == 200:
114
 
                # Parallax returns a JSONified dict(image=image_info)
115
 
                data = json.loads(res.read())['image']
116
 
                return data
117
 
            else:
118
 
                # TODO(jaypipes): log the error?
119
 
                return None
120
 
        finally:
121
 
            c.close()
122
 
 
123
 
    def add_image_metadata(self, image_metadata):
124
 
        """
125
 
        Tells parallax about an image's metadata
126
 
        """
127
 
        try:
128
 
            c = self.connection_type(self.netloc, self.port)
129
 
            body = json.dumps(image_metadata)
130
 
            c.request("POST", "images", body)
131
 
            res = c.getresponse()
132
 
            if res.status == 200:
133
 
                # Parallax returns a JSONified dict(image=image_info)
134
 
                data = json.loads(res.read())['image']
135
 
                return data['id']
136
 
            else:
137
 
                # TODO(jaypipes): log the error?
138
 
                return None
139
 
        finally:
140
 
            c.close()
141
 
 
142
 
    def update_image_metadata(self, image_id, image_metadata):
143
 
        """
144
 
        Updates Parallax's information about an image
145
 
        """
146
 
        try:
147
 
            c = self.connection_type(self.netloc, self.port)
148
 
            body = json.dumps(image_metadata)
149
 
            c.request("PUT", "images/%s" % image_id, body)
150
 
            res = c.getresponse()
151
 
            return res.status == 200
152
 
        finally:
153
 
            c.close()
154
 
 
155
 
    def delete_image_metadata(self, image_id):
156
 
        """
157
 
        Deletes Parallax's information about an image
158
 
        """
159
 
        try:
160
 
            c = self.connection_type(self.netloc, self.port)
161
 
            c.request("DELETE", "images/%s" % image_id)
162
 
            res = c.getresponse()
163
 
            return res.status == 200
164
 
        finally:
165
 
            c.close()
166
 
 
167
 
 
168
 
class GlanceImageService(nova.image.service.BaseImageService):
 
35
GlanceClient = utils.import_class('glance.client.Client')
 
36
 
 
37
 
 
38
class GlanceImageService(service.BaseImageService):
169
39
    """Provides storage and retrieval of disk image objects within Glance."""
170
40
 
171
41
    def __init__(self):
172
 
        self.teller = TellerClient()
173
 
        self.parallax = ParallaxClient()
 
42
        self.client = GlanceClient(FLAGS.glance_host, FLAGS.glance_port)
174
43
 
175
44
    def index(self, context):
176
45
        """
177
 
        Calls out to Parallax for a list of images available
 
46
        Calls out to Glance for a list of images available
178
47
        """
179
 
        images = self.parallax.get_image_index()
180
 
        return images
 
48
        return self.client.get_images()
181
49
 
182
50
    def detail(self, context):
183
51
        """
184
 
        Calls out to Parallax for a list of detailed image information
 
52
        Calls out to Glance for a list of detailed image information
185
53
        """
186
 
        images = self.parallax.get_image_details()
187
 
        return images
 
54
        return self.client.get_images_detailed()
188
55
 
189
56
    def show(self, context, id):
190
57
        """
191
58
        Returns a dict containing image data for the given opaque image id.
192
59
        """
193
 
        image = self.parallax.get_image_metadata(id)
 
60
        image = self.client.get_image_meta(id)
194
61
        if image:
195
62
            return image
196
63
        raise exception.NotFound
202
69
        :raises AlreadyExists if the image already exist.
203
70
 
204
71
        """
205
 
        return self.parallax.add_image_metadata(data)
 
72
        return self.client.add_image(image_meta=data)
206
73
 
207
74
    def update(self, context, image_id, data):
208
75
        """Replace the contents of the given image with the new data.
210
77
        :raises NotFound if the image does not exist.
211
78
 
212
79
        """
213
 
        self.parallax.update_image_metadata(image_id, data)
 
80
        return self.client.update_image(image_id, data)
214
81
 
215
82
    def delete(self, context, image_id):
216
83
        """
219
86
        :raises NotFound if the image does not exist.
220
87
 
221
88
        """
222
 
        self.parallax.delete_image_metadata(image_id)
 
89
        return self.client.delete_image(image_id)
223
90
 
224
91
    def delete_all(self):
225
92
        """