OpenStack Image Management (Glance)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

stubs.py 6.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218
  1. # Copyright 2010-2011 OpenStack Foundation
  2. # All Rights Reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. # not use this file except in compliance with the License. You may obtain
  6. # a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. # WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. # License for the specific language governing permissions and limitations
  14. # under the License.
  15. """Stubouts, mocks and fixtures for the test suite"""
  16. import os
  17. try:
  18. import sendfile
  19. SENDFILE_SUPPORTED = True
  20. except ImportError:
  21. SENDFILE_SUPPORTED = False
  22. import routes
  23. import webob
  24. from glance.api.middleware import context
  25. from glance.api.v1 import router
  26. import glance.common.client
  27. from glance.registry.api import v1 as rserver
  28. from glance.tests import utils
  29. DEBUG = False
  30. class FakeRegistryConnection(object):
  31. def __init__(self, registry=None):
  32. self.registry = registry or rserver
  33. def __call__(self, *args, **kwargs):
  34. # NOTE(flaper87): This method takes
  35. # __init__'s place in the chain.
  36. return self
  37. def connect(self):
  38. return True
  39. def close(self):
  40. return True
  41. def request(self, method, url, body=None, headers=None):
  42. self.req = webob.Request.blank("/" + url.lstrip("/"))
  43. self.req.method = method
  44. if headers:
  45. self.req.headers = headers
  46. if body:
  47. self.req.body = body
  48. def getresponse(self):
  49. mapper = routes.Mapper()
  50. server = self.registry.API(mapper)
  51. # NOTE(markwash): we need to pass through context auth information if
  52. # we have it.
  53. if 'X-Auth-Token' in self.req.headers:
  54. api = utils.FakeAuthMiddleware(server)
  55. else:
  56. api = context.UnauthenticatedContextMiddleware(server)
  57. webob_res = self.req.get_response(api)
  58. return utils.FakeHTTPResponse(status=webob_res.status_int,
  59. headers=webob_res.headers,
  60. data=webob_res.body)
  61. def stub_out_registry_and_store_server(stubs, base_dir, **kwargs):
  62. """Mocks calls to 127.0.0.1 on 9191 and 9292 for testing.
  63. Done so that a real Glance server does not need to be up and
  64. running
  65. """
  66. class FakeSocket(object):
  67. def __init__(self, *args, **kwargs):
  68. pass
  69. def fileno(self):
  70. return 42
  71. class FakeSendFile(object):
  72. def __init__(self, req):
  73. self.req = req
  74. def sendfile(self, o, i, offset, nbytes):
  75. os.lseek(i, offset, os.SEEK_SET)
  76. prev_len = len(self.req.body)
  77. self.req.body += os.read(i, nbytes)
  78. return len(self.req.body) - prev_len
  79. class FakeGlanceConnection(object):
  80. def __init__(self, *args, **kwargs):
  81. self.sock = FakeSocket()
  82. self.stub_force_sendfile = kwargs.get('stub_force_sendfile',
  83. SENDFILE_SUPPORTED)
  84. def connect(self):
  85. return True
  86. def close(self):
  87. return True
  88. def _clean_url(self, url):
  89. # TODO(bcwaldon): Fix the hack that strips off v1
  90. return url.replace('/v1', '', 1) if url.startswith('/v1') else url
  91. def putrequest(self, method, url):
  92. self.req = webob.Request.blank(self._clean_url(url))
  93. if self.stub_force_sendfile:
  94. fake_sendfile = FakeSendFile(self.req)
  95. stubs.Set(sendfile, 'sendfile', fake_sendfile.sendfile)
  96. self.req.method = method
  97. def putheader(self, key, value):
  98. self.req.headers[key] = value
  99. def endheaders(self):
  100. hl = [i.lower() for i in self.req.headers.keys()]
  101. assert not ('content-length' in hl and
  102. 'transfer-encoding' in hl), (
  103. 'Content-Length and Transfer-Encoding are mutually exclusive')
  104. def send(self, data):
  105. # send() is called during chunked-transfer encoding, and
  106. # data is of the form %x\r\n%s\r\n. Strip off the %x and
  107. # only write the actual data in tests.
  108. self.req.body += data.split("\r\n")[1]
  109. def request(self, method, url, body=None, headers=None):
  110. self.req = webob.Request.blank(self._clean_url(url))
  111. self.req.method = method
  112. if headers:
  113. self.req.headers = headers
  114. if body:
  115. self.req.body = body
  116. def getresponse(self):
  117. mapper = routes.Mapper()
  118. api = context.UnauthenticatedContextMiddleware(router.API(mapper))
  119. res = self.req.get_response(api)
  120. # httplib.Response has a read() method...fake it out
  121. def fake_reader():
  122. return res.body
  123. setattr(res, 'read', fake_reader)
  124. return res
  125. def fake_get_connection_type(client):
  126. """Returns the proper connection type."""
  127. DEFAULT_REGISTRY_PORT = 9191
  128. DEFAULT_API_PORT = 9292
  129. if (client.port == DEFAULT_API_PORT and
  130. client.host == '0.0.0.0'):
  131. return FakeGlanceConnection
  132. elif (client.port == DEFAULT_REGISTRY_PORT and
  133. client.host == '0.0.0.0'):
  134. rserver = kwargs.get("registry")
  135. return FakeRegistryConnection(registry=rserver)
  136. def fake_image_iter(self):
  137. for i in self.source.app_iter:
  138. yield i
  139. def fake_sendable(self, body):
  140. force = getattr(self, 'stub_force_sendfile', None)
  141. if force is None:
  142. return self._stub_orig_sendable(body)
  143. else:
  144. if force:
  145. assert glance.common.client.SENDFILE_SUPPORTED
  146. return force
  147. stubs.Set(glance.common.client.BaseClient, 'get_connection_type',
  148. fake_get_connection_type)
  149. setattr(glance.common.client.BaseClient, '_stub_orig_sendable',
  150. glance.common.client.BaseClient._sendable)
  151. stubs.Set(glance.common.client.BaseClient, '_sendable',
  152. fake_sendable)
  153. def stub_out_registry_server(stubs, **kwargs):
  154. """Mocks calls to 127.0.0.1 on 9191 for testing.
  155. Done so that a real Glance Registry server does not need to be up and
  156. running.
  157. """
  158. def fake_get_connection_type(client):
  159. """Returns the proper connection type."""
  160. DEFAULT_REGISTRY_PORT = 9191
  161. if (client.port == DEFAULT_REGISTRY_PORT and
  162. client.host == '0.0.0.0'):
  163. rserver = kwargs.pop("registry", None)
  164. return FakeRegistryConnection(registry=rserver)
  165. def fake_image_iter(self):
  166. for i in self.response.app_iter:
  167. yield i
  168. stubs.Set(glance.common.client.BaseClient, 'get_connection_type',
  169. fake_get_connection_type)