Merge "Allow glance tests to run on Windows"
This commit is contained in:
commit
d501799a6a
@ -32,7 +32,6 @@ CONF = cfg.CONF
|
|||||||
_registry_client = 'glance.registry.client'
|
_registry_client = 'glance.registry.client'
|
||||||
CONF.import_opt('registry_client_protocol', _registry_client)
|
CONF.import_opt('registry_client_protocol', _registry_client)
|
||||||
CONF.import_opt('registry_client_key_file', _registry_client)
|
CONF.import_opt('registry_client_key_file', _registry_client)
|
||||||
CONF.import_opt('registry_client_cert_file', _registry_client)
|
|
||||||
CONF.import_opt('registry_client_ca_file', _registry_client)
|
CONF.import_opt('registry_client_ca_file', _registry_client)
|
||||||
CONF.import_opt('registry_client_insecure', _registry_client)
|
CONF.import_opt('registry_client_insecure', _registry_client)
|
||||||
CONF.import_opt('registry_client_timeout', _registry_client)
|
CONF.import_opt('registry_client_timeout', _registry_client)
|
||||||
|
@ -13,6 +13,8 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
# NOTE(jokke): As per the eventlet commit
|
# NOTE(jokke): As per the eventlet commit
|
||||||
# b756447bab51046dfc6f1e0e299cc997ab343701 there's circular import happening
|
# b756447bab51046dfc6f1e0e299cc997ab343701 there's circular import happening
|
||||||
@ -20,7 +22,13 @@ import eventlet
|
|||||||
# before calling monkey_patch(). This is solved in eventlet 0.22.0 but we
|
# before calling monkey_patch(). This is solved in eventlet 0.22.0 but we
|
||||||
# need to address it before that is widely used around.
|
# need to address it before that is widely used around.
|
||||||
eventlet.hubs.get_hub()
|
eventlet.hubs.get_hub()
|
||||||
eventlet.patcher.monkey_patch()
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
# eventlet monkey patching the os module causes subprocess.Popen to fail
|
||||||
|
# on Windows when using pipes due to missing non-blocking IO support.
|
||||||
|
eventlet.patcher.monkey_patch(os=False)
|
||||||
|
else:
|
||||||
|
eventlet.patcher.monkey_patch()
|
||||||
|
|
||||||
# See http://code.google.com/p/python-nose/issues/detail?id=373
|
# See http://code.google.com/p/python-nose/issues/detail?id=373
|
||||||
# The code below enables tests to work with i18n _() blocks
|
# The code below enables tests to work with i18n _() blocks
|
||||||
|
@ -21,6 +21,7 @@ and Registry server, grabbing the logs of each, cleaning up pidfiles,
|
|||||||
and spinning down the servers.
|
and spinning down the servers.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import abc
|
||||||
import atexit
|
import atexit
|
||||||
import datetime
|
import datetime
|
||||||
import errno
|
import errno
|
||||||
@ -28,12 +29,16 @@ import os
|
|||||||
import platform
|
import platform
|
||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
|
import six
|
||||||
import socket
|
import socket
|
||||||
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
|
from os_win import utilsfactory as os_win_utilsfactory
|
||||||
|
from oslo_config import cfg
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
# NOTE(jokke): simplified transition to py3, behaves like py2 xrange
|
||||||
from six.moves import range
|
from six.moves import range
|
||||||
@ -48,8 +53,18 @@ from glance.tests import utils as test_utils
|
|||||||
execute, get_unused_port = test_utils.execute, test_utils.get_unused_port
|
execute, get_unused_port = test_utils.execute, test_utils.get_unused_port
|
||||||
tracecmd_osmap = {'Linux': 'strace', 'FreeBSD': 'truss'}
|
tracecmd_osmap = {'Linux': 'strace', 'FreeBSD': 'truss'}
|
||||||
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
SQLITE_CONN_TEMPLATE = 'sqlite:///%s/tests.sqlite'
|
||||||
|
else:
|
||||||
|
SQLITE_CONN_TEMPLATE = 'sqlite:////%s/tests.sqlite'
|
||||||
|
|
||||||
class Server(object):
|
|
||||||
|
CONF = cfg.CONF
|
||||||
|
CONF.import_opt('registry_host', 'glance.registry')
|
||||||
|
|
||||||
|
|
||||||
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
class BaseServer(object):
|
||||||
"""
|
"""
|
||||||
Class used to easily manage starting and stopping
|
Class used to easily manage starting and stopping
|
||||||
a server during functional test runs.
|
a server during functional test runs.
|
||||||
@ -131,6 +146,78 @@ class Server(object):
|
|||||||
|
|
||||||
return self.conf_file_name, overridden
|
return self.conf_file_name, overridden
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def start(self, expect_exit=True, expected_exitcode=0, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abc.abstractmethod
|
||||||
|
def stop(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def reload(self, expect_exit=True, expected_exitcode=0, **kwargs):
|
||||||
|
"""
|
||||||
|
Start and stop the service to reload
|
||||||
|
|
||||||
|
Any kwargs passed to this method will override the configuration
|
||||||
|
value in the conf file used in starting the servers.
|
||||||
|
"""
|
||||||
|
self.stop()
|
||||||
|
return self.start(expect_exit=expect_exit,
|
||||||
|
expected_exitcode=expected_exitcode, **kwargs)
|
||||||
|
|
||||||
|
def create_database(self):
|
||||||
|
"""Create database if required for this server"""
|
||||||
|
if self.needs_database:
|
||||||
|
conf_dir = os.path.join(self.test_dir, 'etc')
|
||||||
|
utils.safe_mkdirs(conf_dir)
|
||||||
|
conf_filepath = os.path.join(conf_dir, 'glance-manage.conf')
|
||||||
|
|
||||||
|
with open(conf_filepath, 'w') as conf_file:
|
||||||
|
conf_file.write('[DEFAULT]\n')
|
||||||
|
conf_file.write('sql_connection = %s' % self.sql_connection)
|
||||||
|
conf_file.flush()
|
||||||
|
|
||||||
|
glance_db_env = 'GLANCE_DB_TEST_SQLITE_FILE'
|
||||||
|
if glance_db_env in os.environ:
|
||||||
|
# use the empty db created and cached as a tempfile
|
||||||
|
# instead of spending the time creating a new one
|
||||||
|
db_location = os.environ[glance_db_env]
|
||||||
|
shutil.copyfile(db_location, "%s/tests.sqlite" % self.test_dir)
|
||||||
|
else:
|
||||||
|
cmd = ('%s -m glance.cmd.manage --config-file %s db sync' %
|
||||||
|
(sys.executable, conf_filepath))
|
||||||
|
execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env,
|
||||||
|
expect_exit=True)
|
||||||
|
|
||||||
|
# copy the clean db to a temp location so that it
|
||||||
|
# can be reused for future tests
|
||||||
|
(osf, db_location) = tempfile.mkstemp()
|
||||||
|
os.close(osf)
|
||||||
|
shutil.copyfile('%s/tests.sqlite' % self.test_dir, db_location)
|
||||||
|
os.environ[glance_db_env] = db_location
|
||||||
|
|
||||||
|
# cleanup the temp file when the test suite is
|
||||||
|
# complete
|
||||||
|
def _delete_cached_db():
|
||||||
|
try:
|
||||||
|
os.remove(os.environ[glance_db_env])
|
||||||
|
except Exception:
|
||||||
|
glance_tests.logger.exception(
|
||||||
|
"Error cleaning up the file %s" %
|
||||||
|
os.environ[glance_db_env])
|
||||||
|
atexit.register(_delete_cached_db)
|
||||||
|
|
||||||
|
def dump_log(self):
|
||||||
|
if not self.log_file:
|
||||||
|
return "log_file not set for {name}".format(name=self.server_name)
|
||||||
|
elif not os.path.exists(self.log_file):
|
||||||
|
return "{log_file} for {name} did not exist".format(
|
||||||
|
log_file=self.log_file, name=self.server_name)
|
||||||
|
with open(self.log_file, 'r') as fptr:
|
||||||
|
return fptr.read().strip()
|
||||||
|
|
||||||
|
|
||||||
|
class PosixServer(BaseServer):
|
||||||
def start(self, expect_exit=True, expected_exitcode=0, **kwargs):
|
def start(self, expect_exit=True, expected_exitcode=0, **kwargs):
|
||||||
"""
|
"""
|
||||||
Starts the server.
|
Starts the server.
|
||||||
@ -190,61 +277,6 @@ class Server(object):
|
|||||||
self.sock = None
|
self.sock = None
|
||||||
return (rc, '', '')
|
return (rc, '', '')
|
||||||
|
|
||||||
def reload(self, expect_exit=True, expected_exitcode=0, **kwargs):
|
|
||||||
"""
|
|
||||||
Start and stop the service to reload
|
|
||||||
|
|
||||||
Any kwargs passed to this method will override the configuration
|
|
||||||
value in the conf file used in starting the servers.
|
|
||||||
"""
|
|
||||||
self.stop()
|
|
||||||
return self.start(expect_exit=expect_exit,
|
|
||||||
expected_exitcode=expected_exitcode, **kwargs)
|
|
||||||
|
|
||||||
def create_database(self):
|
|
||||||
"""Create database if required for this server"""
|
|
||||||
if self.needs_database:
|
|
||||||
conf_dir = os.path.join(self.test_dir, 'etc')
|
|
||||||
utils.safe_mkdirs(conf_dir)
|
|
||||||
conf_filepath = os.path.join(conf_dir, 'glance-manage.conf')
|
|
||||||
|
|
||||||
with open(conf_filepath, 'w') as conf_file:
|
|
||||||
conf_file.write('[DEFAULT]\n')
|
|
||||||
conf_file.write('sql_connection = %s' % self.sql_connection)
|
|
||||||
conf_file.flush()
|
|
||||||
|
|
||||||
glance_db_env = 'GLANCE_DB_TEST_SQLITE_FILE'
|
|
||||||
if glance_db_env in os.environ:
|
|
||||||
# use the empty db created and cached as a tempfile
|
|
||||||
# instead of spending the time creating a new one
|
|
||||||
db_location = os.environ[glance_db_env]
|
|
||||||
os.system('cp %s %s/tests.sqlite'
|
|
||||||
% (db_location, self.test_dir))
|
|
||||||
else:
|
|
||||||
cmd = ('%s -m glance.cmd.manage --config-file %s db sync' %
|
|
||||||
(sys.executable, conf_filepath))
|
|
||||||
execute(cmd, no_venv=self.no_venv, exec_env=self.exec_env,
|
|
||||||
expect_exit=True)
|
|
||||||
|
|
||||||
# copy the clean db to a temp location so that it
|
|
||||||
# can be reused for future tests
|
|
||||||
(osf, db_location) = tempfile.mkstemp()
|
|
||||||
os.close(osf)
|
|
||||||
os.system('cp %s/tests.sqlite %s'
|
|
||||||
% (self.test_dir, db_location))
|
|
||||||
os.environ[glance_db_env] = db_location
|
|
||||||
|
|
||||||
# cleanup the temp file when the test suite is
|
|
||||||
# complete
|
|
||||||
def _delete_cached_db():
|
|
||||||
try:
|
|
||||||
os.remove(os.environ[glance_db_env])
|
|
||||||
except Exception:
|
|
||||||
glance_tests.logger.exception(
|
|
||||||
"Error cleaning up the file %s" %
|
|
||||||
os.environ[glance_db_env])
|
|
||||||
atexit.register(_delete_cached_db)
|
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
"""
|
"""
|
||||||
Spin down the server.
|
Spin down the server.
|
||||||
@ -257,14 +289,80 @@ class Server(object):
|
|||||||
rc = test_utils.wait_for_fork(self.process_pid, raise_error=False)
|
rc = test_utils.wait_for_fork(self.process_pid, raise_error=False)
|
||||||
return (rc, '', '')
|
return (rc, '', '')
|
||||||
|
|
||||||
def dump_log(self):
|
|
||||||
if not self.log_file:
|
class Win32Server(BaseServer):
|
||||||
return "log_file not set for {name}".format(name=self.server_name)
|
def __init__(self, *args, **kwargs):
|
||||||
elif not os.path.exists(self.log_file):
|
super(Win32Server, self).__init__(*args, **kwargs)
|
||||||
return "{log_file} for {name} did not exist".format(
|
|
||||||
log_file=self.log_file, name=self.server_name)
|
self._processutils = os_win_utilsfactory.get_processutils()
|
||||||
with open(self.log_file, 'r') as fptr:
|
|
||||||
return fptr.read().strip()
|
def start(self, expect_exit=True, expected_exitcode=0, **kwargs):
|
||||||
|
"""
|
||||||
|
Starts the server.
|
||||||
|
|
||||||
|
Any kwargs passed to this method will override the configuration
|
||||||
|
value in the conf file used in starting the servers.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# Ensure the configuration file is written
|
||||||
|
self.write_conf(**kwargs)
|
||||||
|
|
||||||
|
self.create_database()
|
||||||
|
|
||||||
|
cmd = ("%(server_module)s --config-file %(conf_file_name)s"
|
||||||
|
% {"server_module": self.server_module,
|
||||||
|
"conf_file_name": self.conf_file_name})
|
||||||
|
cmd = "%s -m %s" % (sys.executable, cmd)
|
||||||
|
|
||||||
|
# Passing socket objects on Windows is a bit more cumbersome.
|
||||||
|
# We don't really have to do it.
|
||||||
|
if self.sock:
|
||||||
|
self.sock.close()
|
||||||
|
self.sock = None
|
||||||
|
|
||||||
|
self.process = subprocess.Popen(
|
||||||
|
cmd,
|
||||||
|
env=self.exec_env)
|
||||||
|
self.process_pid = self.process.pid
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.job_handle = self._processutils.kill_process_on_job_close(
|
||||||
|
self.process_pid)
|
||||||
|
except Exception:
|
||||||
|
# Could not associate child process with a job, killing it.
|
||||||
|
self.process.kill()
|
||||||
|
raise
|
||||||
|
|
||||||
|
self.stop_kill = not expect_exit
|
||||||
|
if self.pid_file:
|
||||||
|
pf = open(self.pid_file, 'w')
|
||||||
|
pf.write('%d\n' % self.process_pid)
|
||||||
|
pf.close()
|
||||||
|
|
||||||
|
rc = 0
|
||||||
|
if expect_exit:
|
||||||
|
self.process.communicate()
|
||||||
|
rc = self.process.returncode
|
||||||
|
|
||||||
|
return (rc, '', '')
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
"""
|
||||||
|
Spin down the server.
|
||||||
|
"""
|
||||||
|
if not self.process_pid:
|
||||||
|
raise Exception('Server "%s" process not running.'
|
||||||
|
% self.server_name)
|
||||||
|
|
||||||
|
if self.stop_kill:
|
||||||
|
self.process.terminate()
|
||||||
|
return (0, '', '')
|
||||||
|
|
||||||
|
|
||||||
|
if os.name == 'nt':
|
||||||
|
Server = Win32Server
|
||||||
|
else:
|
||||||
|
Server = PosixServer
|
||||||
|
|
||||||
|
|
||||||
class ApiServer(Server):
|
class ApiServer(Server):
|
||||||
@ -305,7 +403,7 @@ class ApiServer(Server):
|
|||||||
self.disable_path = None
|
self.disable_path = None
|
||||||
|
|
||||||
self.needs_database = True
|
self.needs_database = True
|
||||||
default_sql_connection = 'sqlite:////%s/tests.sqlite' % self.test_dir
|
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
|
||||||
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
||||||
default_sql_connection)
|
default_sql_connection)
|
||||||
self.data_api = kwargs.get("data_api",
|
self.data_api = kwargs.get("data_api",
|
||||||
@ -488,7 +586,7 @@ class ApiServerForMultipleBackend(Server):
|
|||||||
self.disable_path = None
|
self.disable_path = None
|
||||||
|
|
||||||
self.needs_database = True
|
self.needs_database = True
|
||||||
default_sql_connection = 'sqlite:////%s/tests.sqlite' % self.test_dir
|
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
|
||||||
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
||||||
default_sql_connection)
|
default_sql_connection)
|
||||||
self.data_api = kwargs.get("data_api",
|
self.data_api = kwargs.get("data_api",
|
||||||
@ -646,7 +744,7 @@ class RegistryServer(Server):
|
|||||||
self.server_module = 'glance.cmd.%s' % self.server_name
|
self.server_module = 'glance.cmd.%s' % self.server_name
|
||||||
|
|
||||||
self.needs_database = True
|
self.needs_database = True
|
||||||
default_sql_connection = 'sqlite:////%s/tests.sqlite' % self.test_dir
|
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
|
||||||
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
||||||
default_sql_connection)
|
default_sql_connection)
|
||||||
|
|
||||||
@ -732,7 +830,7 @@ class ScrubberDaemon(Server):
|
|||||||
self.metadata_encryption_key = "012345678901234567890123456789ab"
|
self.metadata_encryption_key = "012345678901234567890123456789ab"
|
||||||
self.lock_path = self.test_dir
|
self.lock_path = self.test_dir
|
||||||
|
|
||||||
default_sql_connection = 'sqlite:////%s/tests.sqlite' % self.test_dir
|
default_sql_connection = SQLITE_CONN_TEMPLATE % self.test_dir
|
||||||
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
self.sql_connection = os.environ.get('GLANCE_TEST_SQL_CONNECTION',
|
||||||
default_sql_connection)
|
default_sql_connection)
|
||||||
self.policy_file = policy_file
|
self.policy_file = policy_file
|
||||||
@ -790,6 +888,11 @@ class FunctionalTest(test_utils.BaseTestCase):
|
|||||||
# False in the test SetUps that do not require Scrubber to run.
|
# False in the test SetUps that do not require Scrubber to run.
|
||||||
self.include_scrubber = True
|
self.include_scrubber = True
|
||||||
|
|
||||||
|
# The clients will try to connect to this address. Let's make sure
|
||||||
|
# we're not using the default '0.0.0.0'
|
||||||
|
self.config(bind_host='127.0.0.1',
|
||||||
|
registry_host='127.0.0.1')
|
||||||
|
|
||||||
self.tracecmd = tracecmd_osmap.get(platform.system())
|
self.tracecmd = tracecmd_osmap.get(platform.system())
|
||||||
|
|
||||||
conf_dir = os.path.join(self.test_dir, 'etc')
|
conf_dir = os.path.join(self.test_dir, 'etc')
|
||||||
|
@ -17,6 +17,7 @@
|
|||||||
|
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
|
import time
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
@ -1340,6 +1341,10 @@ class DriverTests(object):
|
|||||||
'deleted': False}
|
'deleted': False}
|
||||||
self.assertEqual(expected, member)
|
self.assertEqual(expected, member)
|
||||||
|
|
||||||
|
# The clock may not be very accurate, for which reason we may
|
||||||
|
# get identical timestamps.
|
||||||
|
time.sleep(0.01)
|
||||||
|
|
||||||
member = self.db_api.image_member_update(self.context,
|
member = self.db_api.image_member_update(self.context,
|
||||||
member_id,
|
member_id,
|
||||||
{'status': 'accepted'})
|
{'status': 'accepted'})
|
||||||
|
@ -346,6 +346,8 @@ class TestScrubber(functional.FunctionalTest):
|
|||||||
def test_scrubber_restore_image_with_daemon_running(self):
|
def test_scrubber_restore_image_with_daemon_running(self):
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
self.scrubber_daemon.start(daemon=True)
|
self.scrubber_daemon.start(daemon=True)
|
||||||
|
# Give the scrubber some time to start.
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
exe_cmd = "%s -m glance.cmd.scrubber" % sys.executable
|
exe_cmd = "%s -m glance.cmd.scrubber" % sys.executable
|
||||||
cmd = ("%s --restore fake_image_id" % exe_cmd)
|
cmd = ("%s --restore fake_image_id" % exe_cmd)
|
||||||
|
@ -45,7 +45,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
self.start_servers(**self.__dict__.copy())
|
self.start_servers(**self.__dict__.copy())
|
||||||
|
|
||||||
# Add an image and verify success
|
# Add an image and verify success
|
||||||
path = "http://%s:%d/v2/images" % ("0.0.0.0", self.api_port)
|
path = "http://%s:%d/v2/images" % ("127.0.0.1", self.api_port)
|
||||||
http = httplib2.Http()
|
http = httplib2.Http()
|
||||||
headers = {'content-type': 'application/json'}
|
headers = {'content-type': 'application/json'}
|
||||||
image_entity = {
|
image_entity = {
|
||||||
@ -61,7 +61,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
data = jsonutils.loads(content)
|
data = jsonutils.loads(content)
|
||||||
image_id = data['id']
|
image_id = data['id']
|
||||||
|
|
||||||
path = "http://%s:%d/v2/images/%s/file" % ("0.0.0.0", self.api_port,
|
path = "http://%s:%d/v2/images/%s/file" % ("127.0.0.1", self.api_port,
|
||||||
image_id)
|
image_id)
|
||||||
headers = {'content-type': 'application/octet-stream'}
|
headers = {'content-type': 'application/octet-stream'}
|
||||||
image_data = "*" * FIVE_KB
|
image_data = "*" * FIVE_KB
|
||||||
@ -87,7 +87,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
|
|
||||||
# Now, we delete the image from the server and verify that
|
# Now, we delete the image from the server and verify that
|
||||||
# the image cache no longer contains the deleted image
|
# the image cache no longer contains the deleted image
|
||||||
path = "http://%s:%d/v2/images/%s" % ("0.0.0.0", self.api_port,
|
path = "http://%s:%d/v2/images/%s" % ("127.0.0.1", self.api_port,
|
||||||
image_id)
|
image_id)
|
||||||
http = httplib2.Http()
|
http = httplib2.Http()
|
||||||
response, content = http.request(path, 'DELETE')
|
response, content = http.request(path, 'DELETE')
|
||||||
@ -107,7 +107,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
self.start_servers(**self.__dict__.copy())
|
self.start_servers(**self.__dict__.copy())
|
||||||
|
|
||||||
# Add an image and verify success
|
# Add an image and verify success
|
||||||
path = "http://%s:%d/v2/images" % ("0.0.0.0", self.api_port)
|
path = "http://%s:%d/v2/images" % ("127.0.0.1", self.api_port)
|
||||||
http = httplib2.Http()
|
http = httplib2.Http()
|
||||||
headers = {'content-type': 'application/json'}
|
headers = {'content-type': 'application/json'}
|
||||||
image_entity = {
|
image_entity = {
|
||||||
@ -123,7 +123,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
data = jsonutils.loads(content)
|
data = jsonutils.loads(content)
|
||||||
image_id = data['id']
|
image_id = data['id']
|
||||||
|
|
||||||
path = "http://%s:%d/v2/images/%s/file" % ("0.0.0.0", self.api_port,
|
path = "http://%s:%d/v2/images/%s/file" % ("127.0.0.1", self.api_port,
|
||||||
image_id)
|
image_id)
|
||||||
headers = {'content-type': 'application/octet-stream'}
|
headers = {'content-type': 'application/octet-stream'}
|
||||||
image_data = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
image_data = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||||
@ -187,7 +187,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
self.start_servers(**self.__dict__.copy())
|
self.start_servers(**self.__dict__.copy())
|
||||||
|
|
||||||
# Add an image and verify success
|
# Add an image and verify success
|
||||||
path = "http://%s:%d/v2/images" % ("0.0.0.0", self.api_port)
|
path = "http://%s:%d/v2/images" % ("127.0.0.1", self.api_port)
|
||||||
http = httplib2.Http()
|
http = httplib2.Http()
|
||||||
headers = {'content-type': 'application/json'}
|
headers = {'content-type': 'application/json'}
|
||||||
image_entity = {
|
image_entity = {
|
||||||
@ -203,7 +203,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
data = jsonutils.loads(content)
|
data = jsonutils.loads(content)
|
||||||
image_id = data['id']
|
image_id = data['id']
|
||||||
|
|
||||||
path = "http://%s:%d/v2/images/%s/file" % ("0.0.0.0", self.api_port,
|
path = "http://%s:%d/v2/images/%s/file" % ("127.0.0.1", self.api_port,
|
||||||
image_id)
|
image_id)
|
||||||
headers = {'content-type': 'application/octet-stream'}
|
headers = {'content-type': 'application/octet-stream'}
|
||||||
image_data = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
image_data = b'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||||
@ -283,7 +283,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
self.start_servers(**self.__dict__.copy())
|
self.start_servers(**self.__dict__.copy())
|
||||||
|
|
||||||
# Add an image and verify success
|
# Add an image and verify success
|
||||||
path = "http://%s:%d/v2/images" % ("0.0.0.0", self.api_port)
|
path = "http://%s:%d/v2/images" % ("127.0.0.1", self.api_port)
|
||||||
http = httplib2.Http()
|
http = httplib2.Http()
|
||||||
headers = {'content-type': 'application/json'}
|
headers = {'content-type': 'application/json'}
|
||||||
image_entity = {
|
image_entity = {
|
||||||
@ -299,7 +299,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
data = jsonutils.loads(content)
|
data = jsonutils.loads(content)
|
||||||
image_id = data['id']
|
image_id = data['id']
|
||||||
|
|
||||||
path = "http://%s:%d/v2/images/%s/file" % ("0.0.0.0", self.api_port,
|
path = "http://%s:%d/v2/images/%s/file" % ("127.0.0.1", self.api_port,
|
||||||
image_id)
|
image_id)
|
||||||
headers = {'content-type': 'application/octet-stream'}
|
headers = {'content-type': 'application/octet-stream'}
|
||||||
image_data = "*" * FIVE_KB
|
image_data = "*" * FIVE_KB
|
||||||
@ -324,7 +324,7 @@ class BaseCacheMiddlewareTest(object):
|
|||||||
|
|
||||||
# Now, we delete the image from the server and verify that
|
# Now, we delete the image from the server and verify that
|
||||||
# the image cache no longer contains the deleted image
|
# the image cache no longer contains the deleted image
|
||||||
path = "http://%s:%d/v2/images/%s" % ("0.0.0.0", self.api_port,
|
path = "http://%s:%d/v2/images/%s" % ("127.0.0.1", self.api_port,
|
||||||
image_id)
|
image_id)
|
||||||
http = httplib2.Http()
|
http = httplib2.Http()
|
||||||
response, content = http.request(path, 'DELETE')
|
response, content = http.request(path, 'DELETE')
|
||||||
@ -347,7 +347,7 @@ class TestImageCacheXattr(functional.FunctionalTest,
|
|||||||
filesystem)
|
filesystem)
|
||||||
"""
|
"""
|
||||||
if getattr(self, 'disabled', False):
|
if getattr(self, 'disabled', False):
|
||||||
return
|
raise self.skipException('Test disabled.')
|
||||||
|
|
||||||
if not getattr(self, 'inited', False):
|
if not getattr(self, 'inited', False):
|
||||||
try:
|
try:
|
||||||
@ -356,7 +356,7 @@ class TestImageCacheXattr(functional.FunctionalTest,
|
|||||||
self.inited = True
|
self.inited = True
|
||||||
self.disabled = True
|
self.disabled = True
|
||||||
self.disabled_message = ("python-xattr not installed.")
|
self.disabled_message = ("python-xattr not installed.")
|
||||||
return
|
raise self.skipException(self.disabled_message)
|
||||||
|
|
||||||
self.inited = True
|
self.inited = True
|
||||||
self.disabled = False
|
self.disabled = False
|
||||||
@ -370,7 +370,7 @@ class TestImageCacheXattr(functional.FunctionalTest,
|
|||||||
self.inited = True
|
self.inited = True
|
||||||
self.disabled = True
|
self.disabled = True
|
||||||
self.disabled_message = ("filesystem does not support xattr")
|
self.disabled_message = ("filesystem does not support xattr")
|
||||||
return
|
raise self.skipException(self.disabled_message)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
super(TestImageCacheXattr, self).tearDown()
|
super(TestImageCacheXattr, self).tearDown()
|
||||||
|
@ -28,7 +28,6 @@ from glance.common import wsgi
|
|||||||
from glance.tests import functional
|
from glance.tests import functional
|
||||||
from glance.tests import utils
|
from glance.tests import utils
|
||||||
|
|
||||||
|
|
||||||
eventlet.patcher.monkey_patch(socket=True)
|
eventlet.patcher.monkey_patch(socket=True)
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,6 +85,12 @@ class TestLogging(functional.FunctionalTest):
|
|||||||
"""
|
"""
|
||||||
Test that we notice when our log file has been rotated
|
Test that we notice when our log file has been rotated
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Moving in-use files is not supported on Windows.
|
||||||
|
# The log handler itself may be configured to rotate files.
|
||||||
|
if os.name == 'nt':
|
||||||
|
raise self.skipException("Unsupported platform.")
|
||||||
|
|
||||||
self.cleanup()
|
self.cleanup()
|
||||||
self.start_servers()
|
self.start_servers()
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ class TestSqlite(functional.FunctionalTest):
|
|||||||
self.cleanup()
|
self.cleanup()
|
||||||
self.start_servers(**self.__dict__.copy())
|
self.start_servers(**self.__dict__.copy())
|
||||||
|
|
||||||
cmd = "sqlite3 tests.sqlite '.schema'"
|
cmd = 'sqlite3 tests.sqlite ".schema"'
|
||||||
exitcode, out, err = execute(cmd, raise_error=True)
|
exitcode, out, err = execute(cmd, raise_error=True)
|
||||||
|
|
||||||
self.assertNotIn('BIGINT', out)
|
self.assertNotIn('BIGINT', out)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
"""Tests for `glance.wsgi`."""
|
"""Tests for `glance.wsgi`."""
|
||||||
|
|
||||||
|
import os
|
||||||
import socket
|
import socket
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -52,4 +53,9 @@ class TestWSGIServer(testtools.TestCase):
|
|||||||
# Should succeed - no timeout
|
# Should succeed - no timeout
|
||||||
self.assertIn(greetings, get_request())
|
self.assertIn(greetings, get_request())
|
||||||
# Should fail - connection timed out so we get nothing from the server
|
# Should fail - connection timed out so we get nothing from the server
|
||||||
self.assertFalse(get_request(delay=1.1))
|
if os.name == 'nt':
|
||||||
|
self.assertRaises(ConnectionAbortedError,
|
||||||
|
get_request,
|
||||||
|
delay=1.1)
|
||||||
|
else:
|
||||||
|
self.assertFalse(get_request(delay=1.1))
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import hashlib
|
import hashlib
|
||||||
import os
|
|
||||||
import signal
|
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
@ -48,16 +46,17 @@ class TestImages(functional.FunctionalTest):
|
|||||||
for i in range(3):
|
for i in range(3):
|
||||||
ret = test_utils.start_http_server("foo_image_id%d" % i,
|
ret = test_utils.start_http_server("foo_image_id%d" % i,
|
||||||
"foo_image%d" % i)
|
"foo_image%d" % i)
|
||||||
setattr(self, 'http_server%d_pid' % i, ret[0])
|
setattr(self, 'http_server%d' % i, ret[1])
|
||||||
setattr(self, 'http_port%d' % i, ret[1])
|
setattr(self, 'http_port%d' % i, ret[2])
|
||||||
self.api_server.use_user_token = True
|
self.api_server.use_user_token = True
|
||||||
self.api_server.send_identity_credentials = True
|
self.api_server.send_identity_credentials = True
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
pid = getattr(self, 'http_server%d_pid' % i, None)
|
httpd = getattr(self, 'http_server%d' % i, None)
|
||||||
if pid:
|
if httpd:
|
||||||
os.kill(pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
super(TestImages, self).tearDown()
|
super(TestImages, self).tearDown()
|
||||||
|
|
||||||
@ -219,7 +218,7 @@ class TestImages(functional.FunctionalTest):
|
|||||||
func_utils.wait_for_status(request_path=path,
|
func_utils.wait_for_status(request_path=path,
|
||||||
request_headers=self._headers(),
|
request_headers=self._headers(),
|
||||||
status='active',
|
status='active',
|
||||||
max_sec=2,
|
max_sec=10,
|
||||||
delay_sec=0.2)
|
delay_sec=0.2)
|
||||||
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
|
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
|
||||||
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
|
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
|
||||||
@ -343,7 +342,7 @@ class TestImages(functional.FunctionalTest):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Start http server locally
|
# Start http server locally
|
||||||
pid, port = test_utils.start_standalone_http_server()
|
thread, httpd, port = test_utils.start_standalone_http_server()
|
||||||
|
|
||||||
image_data_uri = 'http://localhost:%s/' % port
|
image_data_uri = 'http://localhost:%s/' % port
|
||||||
data = jsonutils.dumps({'method': {
|
data = jsonutils.dumps({'method': {
|
||||||
@ -373,7 +372,8 @@ class TestImages(functional.FunctionalTest):
|
|||||||
status='active')
|
status='active')
|
||||||
|
|
||||||
# kill the local http server
|
# kill the local http server
|
||||||
os.kill(pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
# Deleting image should work
|
# Deleting image should work
|
||||||
path = self._url('/v2/images/%s' % image_id)
|
path = self._url('/v2/images/%s' % image_id)
|
||||||
@ -1609,8 +1609,8 @@ class TestImages(functional.FunctionalTest):
|
|||||||
path = self._url('/v2/images/%s' % image_id)
|
path = self._url('/v2/images/%s' % image_id)
|
||||||
media_type = 'application/openstack-images-v2.1-json-patch'
|
media_type = 'application/openstack-images-v2.1-json-patch'
|
||||||
headers = self._headers({'content-type': media_type})
|
headers = self._headers({'content-type': media_type})
|
||||||
http_server_pid, http_port = test_utils.start_http_server(image_id,
|
thread, httpd, http_port = test_utils.start_http_server(image_id,
|
||||||
"image-1")
|
"image-1")
|
||||||
values = [{'url': 'http://127.0.0.1:%s/image-1' % http_port,
|
values = [{'url': 'http://127.0.0.1:%s/image-1' % http_port,
|
||||||
'metadata': {'idx': '0'}}]
|
'metadata': {'idx': '0'}}]
|
||||||
doc = [{'op': 'replace',
|
doc = [{'op': 'replace',
|
||||||
@ -1627,7 +1627,8 @@ class TestImages(functional.FunctionalTest):
|
|||||||
self.assertEqual(http.OK, response.status_code)
|
self.assertEqual(http.OK, response.status_code)
|
||||||
|
|
||||||
# Stop http server used to update image location
|
# Stop http server used to update image location
|
||||||
os.kill(http_server_pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
# Download an image should raise HTTPServiceUnavailable
|
# Download an image should raise HTTPServiceUnavailable
|
||||||
path = self._url('/v2/images/%s/file' % image_id)
|
path = self._url('/v2/images/%s/file' % image_id)
|
||||||
@ -3895,14 +3896,15 @@ class TestImageLocationSelectionStrategy(functional.FunctionalTest):
|
|||||||
for i in range(3):
|
for i in range(3):
|
||||||
ret = test_utils.start_http_server("foo_image_id%d" % i,
|
ret = test_utils.start_http_server("foo_image_id%d" % i,
|
||||||
"foo_image%d" % i)
|
"foo_image%d" % i)
|
||||||
setattr(self, 'http_server%d_pid' % i, ret[0])
|
setattr(self, 'http_server%d' % i, ret[1])
|
||||||
setattr(self, 'http_port%d' % i, ret[1])
|
setattr(self, 'http_port%d' % i, ret[2])
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
pid = getattr(self, 'http_server%d_pid' % i, None)
|
httpd = getattr(self, 'http_server%d' % i, None)
|
||||||
if pid:
|
if httpd:
|
||||||
os.kill(pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
super(TestImageLocationSelectionStrategy, self).tearDown()
|
super(TestImageLocationSelectionStrategy, self).tearDown()
|
||||||
|
|
||||||
@ -4453,14 +4455,15 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
for i in range(3):
|
for i in range(3):
|
||||||
ret = test_utils.start_http_server("foo_image_id%d" % i,
|
ret = test_utils.start_http_server("foo_image_id%d" % i,
|
||||||
"foo_image%d" % i)
|
"foo_image%d" % i)
|
||||||
setattr(self, 'http_server%d_pid' % i, ret[0])
|
setattr(self, 'http_server%d' % i, ret[1])
|
||||||
setattr(self, 'http_port%d' % i, ret[1])
|
setattr(self, 'http_port%d' % i, ret[2])
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
pid = getattr(self, 'http_server%d_pid' % i, None)
|
httpd = getattr(self, 'http_server%d' % i, None)
|
||||||
if pid:
|
if httpd:
|
||||||
os.kill(pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
super(TestImagesMultipleBackend, self).tearDown()
|
super(TestImagesMultipleBackend, self).tearDown()
|
||||||
|
|
||||||
@ -4605,7 +4608,7 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
func_utils.wait_for_status(request_path=path,
|
func_utils.wait_for_status(request_path=path,
|
||||||
request_headers=self._headers(),
|
request_headers=self._headers(),
|
||||||
status='active',
|
status='active',
|
||||||
max_sec=2,
|
max_sec=15,
|
||||||
delay_sec=0.2)
|
delay_sec=0.2)
|
||||||
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
|
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
|
||||||
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
|
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
|
||||||
@ -4766,7 +4769,7 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
func_utils.wait_for_status(request_path=path,
|
func_utils.wait_for_status(request_path=path,
|
||||||
request_headers=self._headers(),
|
request_headers=self._headers(),
|
||||||
status='active',
|
status='active',
|
||||||
max_sec=2,
|
max_sec=15,
|
||||||
delay_sec=0.2)
|
delay_sec=0.2)
|
||||||
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
|
expect_c = six.text_type(hashlib.md5(image_data).hexdigest())
|
||||||
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
|
expect_h = six.text_type(hashlib.sha512(image_data).hexdigest())
|
||||||
@ -4909,7 +4912,7 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Start http server locally
|
# Start http server locally
|
||||||
pid, port = test_utils.start_standalone_http_server()
|
thread, httpd, port = test_utils.start_standalone_http_server()
|
||||||
|
|
||||||
image_data_uri = 'http://localhost:%s/' % port
|
image_data_uri = 'http://localhost:%s/' % port
|
||||||
data = jsonutils.dumps({'method': {
|
data = jsonutils.dumps({'method': {
|
||||||
@ -4939,7 +4942,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
status='active')
|
status='active')
|
||||||
|
|
||||||
# kill the local http server
|
# kill the local http server
|
||||||
os.kill(pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
# Ensure image is created in default backend
|
# Ensure image is created in default backend
|
||||||
path = self._url('/v2/images/%s' % image_id)
|
path = self._url('/v2/images/%s' % image_id)
|
||||||
response = requests.get(path, headers=self._headers())
|
response = requests.get(path, headers=self._headers())
|
||||||
@ -5069,7 +5073,7 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
})
|
})
|
||||||
|
|
||||||
# Start http server locally
|
# Start http server locally
|
||||||
pid, port = test_utils.start_standalone_http_server()
|
thread, httpd, port = test_utils.start_standalone_http_server()
|
||||||
|
|
||||||
image_data_uri = 'http://localhost:%s/' % port
|
image_data_uri = 'http://localhost:%s/' % port
|
||||||
data = jsonutils.dumps({'method': {
|
data = jsonutils.dumps({'method': {
|
||||||
@ -5099,7 +5103,8 @@ class TestImagesMultipleBackend(functional.MultipleBackendFunctionalTest):
|
|||||||
status='active')
|
status='active')
|
||||||
|
|
||||||
# kill the local http server
|
# kill the local http server
|
||||||
os.kill(pid, signal.SIGKILL)
|
httpd.shutdown()
|
||||||
|
httpd.server_close()
|
||||||
|
|
||||||
# Ensure image is created in different backend
|
# Ensure image is created in different backend
|
||||||
path = self._url('/v2/images/%s' % image_id)
|
path = self._url('/v2/images/%s' % image_id)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
import os.path
|
import os.path
|
||||||
|
import shutil
|
||||||
import tempfile
|
import tempfile
|
||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
@ -163,8 +164,7 @@ class ApiTest(test_utils.BaseTestCase):
|
|||||||
# use the empty db created and cached as a tempfile
|
# use the empty db created and cached as a tempfile
|
||||||
# instead of spending the time creating a new one
|
# instead of spending the time creating a new one
|
||||||
db_location = os.environ[glance_db_env]
|
db_location = os.environ[glance_db_env]
|
||||||
test_utils.execute('cp %s %s/tests.sqlite'
|
shutil.copyfile(db_location, "%s/tests.sqlite" % self.test_dir)
|
||||||
% (db_location, self.test_dir))
|
|
||||||
else:
|
else:
|
||||||
test_utils.db_sync()
|
test_utils.db_sync()
|
||||||
|
|
||||||
@ -172,8 +172,7 @@ class ApiTest(test_utils.BaseTestCase):
|
|||||||
# can be reused for future tests
|
# can be reused for future tests
|
||||||
(osf, db_location) = tempfile.mkstemp()
|
(osf, db_location) = tempfile.mkstemp()
|
||||||
os.close(osf)
|
os.close(osf)
|
||||||
test_utils.execute('cp %s/tests.sqlite %s'
|
shutil.copyfile('%s/tests.sqlite' % self.test_dir, db_location)
|
||||||
% (self.test_dir, db_location))
|
|
||||||
os.environ[glance_db_env] = db_location
|
os.environ[glance_db_env] = db_location
|
||||||
|
|
||||||
# cleanup the temp file when the test suite is
|
# cleanup the temp file when the test suite is
|
||||||
|
@ -135,8 +135,8 @@ class TestImportTask(test_utils.BaseTestCase):
|
|||||||
self.assertFalse(os.path.exists(tmp_image_path))
|
self.assertFalse(os.path.exists(tmp_image_path))
|
||||||
self.assertTrue(os.path.exists(image_path))
|
self.assertTrue(os.path.exists(image_path))
|
||||||
self.assertEqual(1, len(list(self.image.locations)))
|
self.assertEqual(1, len(list(self.image.locations)))
|
||||||
self.assertEqual("file://%s/%s" % (self.test_dir,
|
self.assertEqual("file://%s%s%s" % (self.test_dir, os.sep,
|
||||||
self.image.image_id),
|
self.image.image_id),
|
||||||
self.image.locations[0]['url'])
|
self.image.locations[0]['url'])
|
||||||
|
|
||||||
self._assert_qemu_process_limits(tmock)
|
self._assert_qemu_process_limits(tmock)
|
||||||
|
@ -108,11 +108,9 @@ class IsolatedUnitTest(StoreClearingUnitTest):
|
|||||||
DEFAULT_REGISTRY_PORT = 9191
|
DEFAULT_REGISTRY_PORT = 9191
|
||||||
DEFAULT_API_PORT = 9292
|
DEFAULT_API_PORT = 9292
|
||||||
|
|
||||||
if (client.port == DEFAULT_API_PORT and
|
if client.port == DEFAULT_API_PORT:
|
||||||
client.host == '0.0.0.0'):
|
|
||||||
return stubs.FakeGlanceConnection
|
return stubs.FakeGlanceConnection
|
||||||
elif (client.port == DEFAULT_REGISTRY_PORT and
|
elif client.port == DEFAULT_REGISTRY_PORT:
|
||||||
client.host == '0.0.0.0'):
|
|
||||||
return stubs.FakeRegistryConnection(registry=self.registry)
|
return stubs.FakeRegistryConnection(registry=self.registry)
|
||||||
|
|
||||||
self.patcher = mock.patch(
|
self.patcher = mock.patch(
|
||||||
|
@ -588,8 +588,11 @@ class ServerTest(test_utils.BaseTestCase):
|
|||||||
keepalive=False,
|
keepalive=False,
|
||||||
socket_timeout=900)
|
socket_timeout=900)
|
||||||
|
|
||||||
def test_number_of_workers(self):
|
def test_number_of_workers_posix(self):
|
||||||
"""Ensure the number of workers matches num cpus limited to 8."""
|
"""Ensure the number of workers matches num cpus limited to 8."""
|
||||||
|
if os.name == 'nt':
|
||||||
|
raise self.skipException("Unsupported platform.")
|
||||||
|
|
||||||
def pid():
|
def pid():
|
||||||
i = 1
|
i = 1
|
||||||
while True:
|
while True:
|
||||||
|
@ -281,6 +281,7 @@ class ImageCacheTestCase(object):
|
|||||||
self.assertEqual(['0', '1', '2'],
|
self.assertEqual(['0', '1', '2'],
|
||||||
self.cache.get_queued_images())
|
self.cache.get_queued_images())
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_open_for_write_good(self):
|
def test_open_for_write_good(self):
|
||||||
"""
|
"""
|
||||||
Test to see if open_for_write works in normal case
|
Test to see if open_for_write works in normal case
|
||||||
@ -300,6 +301,7 @@ class ImageCacheTestCase(object):
|
|||||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||||
self.assertFalse(os.path.exists(invalid_file_path))
|
self.assertFalse(os.path.exists(invalid_file_path))
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_open_for_write_with_exception(self):
|
def test_open_for_write_with_exception(self):
|
||||||
"""
|
"""
|
||||||
Test to see if open_for_write works in a failure case for each driver
|
Test to see if open_for_write works in a failure case for each driver
|
||||||
@ -324,6 +326,7 @@ class ImageCacheTestCase(object):
|
|||||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||||
self.assertTrue(os.path.exists(invalid_file_path))
|
self.assertTrue(os.path.exists(invalid_file_path))
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_caching_iterator(self):
|
def test_caching_iterator(self):
|
||||||
"""
|
"""
|
||||||
Test to see if the caching iterator interacts properly with the driver
|
Test to see if the caching iterator interacts properly with the driver
|
||||||
@ -351,6 +354,7 @@ class ImageCacheTestCase(object):
|
|||||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||||
self.assertFalse(os.path.exists(invalid_file_path))
|
self.assertFalse(os.path.exists(invalid_file_path))
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_caching_iterator_handles_backend_failure(self):
|
def test_caching_iterator_handles_backend_failure(self):
|
||||||
"""
|
"""
|
||||||
Test that when the backend fails, caching_iter does not continue trying
|
Test that when the backend fails, caching_iter does not continue trying
|
||||||
@ -374,6 +378,7 @@ class ImageCacheTestCase(object):
|
|||||||
# make sure bad image was not cached
|
# make sure bad image was not cached
|
||||||
self.assertFalse(self.cache.is_cached(image_id))
|
self.assertFalse(self.cache.is_cached(image_id))
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_caching_iterator_falloffend(self):
|
def test_caching_iterator_falloffend(self):
|
||||||
"""
|
"""
|
||||||
Test to see if the caching iterator interacts properly with the driver
|
Test to see if the caching iterator interacts properly with the driver
|
||||||
@ -402,6 +407,7 @@ class ImageCacheTestCase(object):
|
|||||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||||
self.assertTrue(os.path.exists(invalid_file_path))
|
self.assertTrue(os.path.exists(invalid_file_path))
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_gate_caching_iter_good_checksum(self):
|
def test_gate_caching_iter_good_checksum(self):
|
||||||
image = b"12345678990abcdefghijklmnop"
|
image = b"12345678990abcdefghijklmnop"
|
||||||
image_id = 123
|
image_id = 123
|
||||||
@ -417,6 +423,7 @@ class ImageCacheTestCase(object):
|
|||||||
# checksum is valid, fake image should be cached:
|
# checksum is valid, fake image should be cached:
|
||||||
self.assertTrue(cache.is_cached(image_id))
|
self.assertTrue(cache.is_cached(image_id))
|
||||||
|
|
||||||
|
@skip_if_disabled
|
||||||
def test_gate_caching_iter_bad_checksum(self):
|
def test_gate_caching_iter_bad_checksum(self):
|
||||||
image = b"12345678990abcdefghijklmnop"
|
image = b"12345678990abcdefghijklmnop"
|
||||||
image_id = 123
|
image_id = 123
|
||||||
|
@ -165,7 +165,9 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||||||
'metadata': {}, 'status': 'active'}],
|
'metadata': {}, 'status': 'active'}],
|
||||||
disk_format='raw',
|
disk_format='raw',
|
||||||
container_format='bare',
|
container_format='bare',
|
||||||
status='active'),
|
status='active',
|
||||||
|
created_at=DATETIME,
|
||||||
|
updated_at=DATETIME),
|
||||||
_db_fixture(UUID2, owner=TENANT1, checksum=CHKSUM1,
|
_db_fixture(UUID2, owner=TENANT1, checksum=CHKSUM1,
|
||||||
os_hash_algo=FAKEHASHALGO, os_hash_value=MULTIHASH2,
|
os_hash_algo=FAKEHASHALGO, os_hash_value=MULTIHASH2,
|
||||||
name='2', size=512, virtual_size=2048,
|
name='2', size=512, virtual_size=2048,
|
||||||
@ -175,13 +177,19 @@ class TestImagesController(base.IsolatedUnitTest):
|
|||||||
status='active',
|
status='active',
|
||||||
tags=['redhat', '64bit', 'power'],
|
tags=['redhat', '64bit', 'power'],
|
||||||
properties={'hypervisor_type': 'kvm', 'foo': 'bar',
|
properties={'hypervisor_type': 'kvm', 'foo': 'bar',
|
||||||
'bar': 'foo'}),
|
'bar': 'foo'},
|
||||||
|
created_at=DATETIME + datetime.timedelta(seconds=1),
|
||||||
|
updated_at=DATETIME + datetime.timedelta(seconds=1)),
|
||||||
_db_fixture(UUID3, owner=TENANT3, checksum=CHKSUM1,
|
_db_fixture(UUID3, owner=TENANT3, checksum=CHKSUM1,
|
||||||
os_hash_algo=FAKEHASHALGO, os_hash_value=MULTIHASH2,
|
os_hash_algo=FAKEHASHALGO, os_hash_value=MULTIHASH2,
|
||||||
name='3', size=512, virtual_size=2048,
|
name='3', size=512, virtual_size=2048,
|
||||||
visibility='public', tags=['windows', '64bit', 'x86']),
|
visibility='public', tags=['windows', '64bit', 'x86'],
|
||||||
|
created_at=DATETIME + datetime.timedelta(seconds=2),
|
||||||
|
updated_at=DATETIME + datetime.timedelta(seconds=2)),
|
||||||
_db_fixture(UUID4, owner=TENANT4, name='4',
|
_db_fixture(UUID4, owner=TENANT4, name='4',
|
||||||
size=1024, virtual_size=3072),
|
size=1024, virtual_size=3072,
|
||||||
|
created_at=DATETIME + datetime.timedelta(seconds=3),
|
||||||
|
updated_at=DATETIME + datetime.timedelta(seconds=3)),
|
||||||
]
|
]
|
||||||
[self.db.image_create(None, image) for image in self.images]
|
[self.db.image_create(None, image) for image in self.images]
|
||||||
|
|
||||||
@ -4649,7 +4657,8 @@ class TestMultiImagesController(base.MultiIsolatedUnitTest):
|
|||||||
'metadata': {}, 'status': 'active'}],
|
'metadata': {}, 'status': 'active'}],
|
||||||
disk_format='raw',
|
disk_format='raw',
|
||||||
container_format='bare',
|
container_format='bare',
|
||||||
status='active'),
|
status='active',
|
||||||
|
created_at=DATETIME),
|
||||||
_db_fixture(UUID2, owner=TENANT1, checksum=CHKSUM1,
|
_db_fixture(UUID2, owner=TENANT1, checksum=CHKSUM1,
|
||||||
name='2', size=512, virtual_size=2048,
|
name='2', size=512, virtual_size=2048,
|
||||||
visibility='public',
|
visibility='public',
|
||||||
@ -4658,12 +4667,15 @@ class TestMultiImagesController(base.MultiIsolatedUnitTest):
|
|||||||
status='active',
|
status='active',
|
||||||
tags=['redhat', '64bit', 'power'],
|
tags=['redhat', '64bit', 'power'],
|
||||||
properties={'hypervisor_type': 'kvm', 'foo': 'bar',
|
properties={'hypervisor_type': 'kvm', 'foo': 'bar',
|
||||||
'bar': 'foo'}),
|
'bar': 'foo'},
|
||||||
|
created_at=DATETIME + datetime.timedelta(seconds=1)),
|
||||||
_db_fixture(UUID3, owner=TENANT3, checksum=CHKSUM1,
|
_db_fixture(UUID3, owner=TENANT3, checksum=CHKSUM1,
|
||||||
name='3', size=512, virtual_size=2048,
|
name='3', size=512, virtual_size=2048,
|
||||||
visibility='public', tags=['windows', '64bit', 'x86']),
|
visibility='public', tags=['windows', '64bit', 'x86'],
|
||||||
|
created_at=DATETIME + datetime.timedelta(seconds=2)),
|
||||||
_db_fixture(UUID4, owner=TENANT4, name='4',
|
_db_fixture(UUID4, owner=TENANT4, name='4',
|
||||||
size=1024, virtual_size=3072),
|
size=1024, virtual_size=3072,
|
||||||
|
created_at=DATETIME + datetime.timedelta(seconds=3)),
|
||||||
]
|
]
|
||||||
[self.db.image_create(None, image) for image in self.images]
|
[self.db.image_create(None, image) for image in self.images]
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class TestRegistryV2Client(base.IsolatedUnitTest,
|
|||||||
created_at=uuid2_time)]
|
created_at=uuid2_time)]
|
||||||
self.destroy_fixtures()
|
self.destroy_fixtures()
|
||||||
self.create_fixtures()
|
self.create_fixtures()
|
||||||
self.client = rclient.RegistryClient("0.0.0.0")
|
self.client = rclient.RegistryClient("127.0.0.1")
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
"""Clear the test environment"""
|
"""Clear the test environment"""
|
||||||
|
@ -22,6 +22,7 @@ import shlex
|
|||||||
import shutil
|
import shutil
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
import threading
|
||||||
|
|
||||||
from alembic import command as alembic_command
|
from alembic import command as alembic_command
|
||||||
import fixtures
|
import fixtures
|
||||||
@ -176,7 +177,11 @@ class depends_on_exe(object):
|
|||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
def _runner(*args, **kw):
|
def _runner(*args, **kw):
|
||||||
cmd = 'which %s' % self.exe
|
if os.name != 'nt':
|
||||||
|
cmd = 'which %s' % self.exe
|
||||||
|
else:
|
||||||
|
cmd = 'where.exe', '%s' % self.exe
|
||||||
|
|
||||||
exitcode, out, err = execute(cmd, raise_error=False)
|
exitcode, out, err = execute(cmd, raise_error=False)
|
||||||
if exitcode != 0:
|
if exitcode != 0:
|
||||||
args[0].disabled_message = 'test requires exe: %s' % self.exe
|
args[0].disabled_message = 'test requires exe: %s' % self.exe
|
||||||
@ -325,7 +330,11 @@ def execute(cmd,
|
|||||||
path_ext = [os.path.join(os.getcwd(), 'bin')]
|
path_ext = [os.path.join(os.getcwd(), 'bin')]
|
||||||
|
|
||||||
# Also jack in the path cmd comes from, if it's absolute
|
# Also jack in the path cmd comes from, if it's absolute
|
||||||
args = shlex.split(cmd)
|
if os.name != 'nt':
|
||||||
|
args = shlex.split(cmd)
|
||||||
|
else:
|
||||||
|
args = cmd
|
||||||
|
|
||||||
executable = args[0]
|
executable = args[0]
|
||||||
if os.path.isabs(executable):
|
if os.path.isabs(executable):
|
||||||
path_ext.append(os.path.dirname(executable))
|
path_ext.append(os.path.dirname(executable))
|
||||||
@ -484,7 +493,7 @@ def start_http_server(image_id, image_data):
|
|||||||
self.send_response(http.OK)
|
self.send_response(http.OK)
|
||||||
self.send_header('Content-Length', str(len(fixture)))
|
self.send_header('Content-Length', str(len(fixture)))
|
||||||
self.end_headers()
|
self.end_headers()
|
||||||
self.wfile.write(fixture)
|
self.wfile.write(six.b(fixture))
|
||||||
return
|
return
|
||||||
|
|
||||||
def do_HEAD(self):
|
def do_HEAD(self):
|
||||||
@ -510,11 +519,11 @@ def start_http_server(image_id, image_data):
|
|||||||
httpd = BaseHTTPServer.HTTPServer(server_address, handler_class)
|
httpd = BaseHTTPServer.HTTPServer(server_address, handler_class)
|
||||||
port = httpd.socket.getsockname()[1]
|
port = httpd.socket.getsockname()[1]
|
||||||
|
|
||||||
pid = os.fork()
|
thread = threading.Thread(target=httpd.serve_forever)
|
||||||
if pid == 0:
|
thread.daemon = True
|
||||||
httpd.serve_forever()
|
thread.start()
|
||||||
else:
|
|
||||||
return pid, port
|
return thread, httpd, port
|
||||||
|
|
||||||
|
|
||||||
class RegistryAPIMixIn(object):
|
class RegistryAPIMixIn(object):
|
||||||
@ -730,8 +739,8 @@ def start_standalone_http_server():
|
|||||||
httpd = BaseHTTPServer.HTTPServer(server_address, handler_class)
|
httpd = BaseHTTPServer.HTTPServer(server_address, handler_class)
|
||||||
port = httpd.socket.getsockname()[1]
|
port = httpd.socket.getsockname()[1]
|
||||||
|
|
||||||
pid = os.fork()
|
thread = threading.Thread(target=httpd.serve_forever)
|
||||||
if pid == 0:
|
thread.daemon = True
|
||||||
httpd.serve_forever()
|
thread.start()
|
||||||
else:
|
|
||||||
return pid, port
|
return thread, httpd, port
|
||||||
|
Loading…
Reference in New Issue
Block a user