Remove Windows OS support
Windows OS support was deprecated in 2024.1 cycle because Winstackers
project was retired[1]. Remove the support now to get rid of os-win
which was also abandoned.
[1] a8bed388f2
Change-Id: I737279c93a6231ebf2e8c87810040ce48622f4fc
This commit is contained in:
parent
704b24fd67
commit
acab9351a1
@ -26,10 +26,6 @@ of its features. Some examples include the ``qemu-img`` utility used by the
|
|||||||
tasks feature, ``pydev`` to debug using popular IDEs, ``python-xattr`` for
|
tasks feature, ``pydev`` to debug using popular IDEs, ``python-xattr`` for
|
||||||
Image Cache using "xattr" driver.
|
Image Cache using "xattr" driver.
|
||||||
|
|
||||||
Additionally, some libraries like ``xattr`` are not compatible when
|
|
||||||
using Glance on Windows (see :ref:`the documentation on config options
|
|
||||||
affecting the Image Cache <configuring>`).
|
|
||||||
|
|
||||||
|
|
||||||
Guideline to include your requirement in the requirements.txt file
|
Guideline to include your requirement in the requirements.txt file
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
@ -1756,8 +1756,7 @@ One main configuration file option affects the image cache.
|
|||||||
and requires that the filesystem containing ``image_cache_dir`` have
|
and requires that the filesystem containing ``image_cache_dir`` have
|
||||||
access times tracked for all files (in other words, the noatime option
|
access times tracked for all files (in other words, the noatime option
|
||||||
CANNOT be set for that filesystem). In addition, ``user_xattr`` must be
|
CANNOT be set for that filesystem). In addition, ``user_xattr`` must be
|
||||||
set on the filesystem's description line in fstab. Because of these
|
set on the filesystem's description line in fstab.
|
||||||
requirements, the ``xattr`` cache driver is not available on Windows.
|
|
||||||
|
|
||||||
``image_cache_sqlite_db=DB_FILE``
|
``image_cache_sqlite_db=DB_FILE``
|
||||||
Optional.
|
Optional.
|
||||||
|
@ -25,13 +25,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
|
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()
|
|
||||||
|
|
||||||
# Monkey patch the original current_thread to use the up-to-date _active
|
# Monkey patch the original current_thread to use the up-to-date _active
|
||||||
# global variable. See https://bugs.launchpad.net/bugs/1863021 and
|
# global variable. See https://bugs.launchpad.net/bugs/1863021 and
|
||||||
@ -66,7 +60,6 @@ from glance import version
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.import_group("profiler", "glance.common.wsgi")
|
CONF.import_group("profiler", "glance.common.wsgi")
|
||||||
logging.register_options(CONF)
|
logging.register_options(CONF)
|
||||||
wsgi.register_cli_opts()
|
|
||||||
|
|
||||||
# NOTE(rosmaita): Any new exceptions added should preserve the current
|
# NOTE(rosmaita): Any new exceptions added should preserve the current
|
||||||
# error codes for backward compatibility. The value 99 is returned
|
# error codes for backward compatibility. The value 99 is returned
|
||||||
|
@ -23,13 +23,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
|
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()
|
|
||||||
|
|
||||||
# Monkey patch the original current_thread to use the up-to-date _active
|
# Monkey patch the original current_thread to use the up-to-date _active
|
||||||
# global variable. See https://bugs.launchpad.net/bugs/1863021 and
|
# global variable. See https://bugs.launchpad.net/bugs/1863021 and
|
||||||
@ -49,7 +43,6 @@ if os.path.exists(os.path.join(possible_topdir, 'glance', '__init__.py')):
|
|||||||
sys.path.insert(0, possible_topdir)
|
sys.path.insert(0, possible_topdir)
|
||||||
|
|
||||||
import glance_store
|
import glance_store
|
||||||
from os_win import utilsfactory as os_win_utilsfactory
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
@ -64,18 +57,7 @@ CONF.set_default(name='use_stderr', default=True)
|
|||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
# Used on Window, ensuring that a single scrubber can run at a time.
|
|
||||||
mutex = None
|
|
||||||
mutex_acquired = False
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if os.name == 'nt':
|
|
||||||
# We can't rely on process names on Windows as there may be
|
|
||||||
# wrappers with the same name.
|
|
||||||
mutex = os_win_utilsfactory.get_mutex(
|
|
||||||
name='Global\\glance-scrubber')
|
|
||||||
mutex_acquired = mutex.acquire(timeout_ms=0)
|
|
||||||
|
|
||||||
CONF.register_cli_opts(scrubber.scrubber_cmd_cli_opts)
|
CONF.register_cli_opts(scrubber.scrubber_cmd_cli_opts)
|
||||||
CONF.register_opts(scrubber.scrubber_cmd_opts)
|
CONF.register_opts(scrubber.scrubber_cmd_opts)
|
||||||
|
|
||||||
@ -99,12 +81,7 @@ def main():
|
|||||||
app = scrubber.Scrubber(glance_store)
|
app = scrubber.Scrubber(glance_store)
|
||||||
|
|
||||||
if CONF.restore:
|
if CONF.restore:
|
||||||
if os.name == 'nt':
|
if scrubber_already_running():
|
||||||
scrubber_already_running = not mutex_acquired
|
|
||||||
else:
|
|
||||||
scrubber_already_running = scrubber_already_running_posix()
|
|
||||||
|
|
||||||
if scrubber_already_running:
|
|
||||||
already_running_msg = (
|
already_running_msg = (
|
||||||
"ERROR: glance-scrubber is already running. "
|
"ERROR: glance-scrubber is already running. "
|
||||||
"Please ensure that the daemon is stopped.")
|
"Please ensure that the daemon is stopped.")
|
||||||
@ -121,12 +98,9 @@ def main():
|
|||||||
sys.exit("ERROR: %s" % e)
|
sys.exit("ERROR: %s" % e)
|
||||||
except RuntimeError as e:
|
except RuntimeError as e:
|
||||||
sys.exit("ERROR: %s" % e)
|
sys.exit("ERROR: %s" % e)
|
||||||
finally:
|
|
||||||
if mutex and mutex_acquired:
|
|
||||||
mutex.release()
|
|
||||||
|
|
||||||
|
|
||||||
def scrubber_already_running_posix():
|
def scrubber_already_running():
|
||||||
# Try to check the glance-scrubber is running or not.
|
# Try to check the glance-scrubber is running or not.
|
||||||
# 1. Try to find the pid file if scrubber is controlled by
|
# 1. Try to find the pid file if scrubber is controlled by
|
||||||
# glance-control
|
# glance-control
|
||||||
|
@ -24,10 +24,7 @@ import abc
|
|||||||
import errno
|
import errno
|
||||||
import functools
|
import functools
|
||||||
import os
|
import os
|
||||||
import re
|
|
||||||
import signal
|
import signal
|
||||||
import struct
|
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
@ -35,7 +32,6 @@ from eventlet.green import socket
|
|||||||
import eventlet.greenio
|
import eventlet.greenio
|
||||||
import eventlet.wsgi
|
import eventlet.wsgi
|
||||||
import glance_store
|
import glance_store
|
||||||
from os_win import utilsfactory as os_win_utilsfactory
|
|
||||||
from oslo_concurrency import processutils
|
from oslo_concurrency import processutils
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
@ -252,13 +248,6 @@ store_opts = [
|
|||||||
'using comma.')),
|
'using comma.')),
|
||||||
]
|
]
|
||||||
|
|
||||||
cli_opts = [
|
|
||||||
cfg.StrOpt('pipe-handle',
|
|
||||||
help='This argument is used internally on Windows. Glance '
|
|
||||||
'passes a pipe handle to child processes, which is then '
|
|
||||||
'used for inter-process communication.'),
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -286,17 +275,9 @@ RESERVED_STORES = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def register_cli_opts():
|
|
||||||
CONF.register_cli_opts(cli_opts)
|
|
||||||
|
|
||||||
|
|
||||||
def get_num_workers():
|
def get_num_workers():
|
||||||
"""Return the configured number of workers."""
|
"""Return the configured number of workers."""
|
||||||
|
|
||||||
# Windows only: we're already running on the worker side.
|
|
||||||
if os.name == 'nt' and getattr(CONF, 'pipe_handle', None):
|
|
||||||
return 0
|
|
||||||
|
|
||||||
if CONF.workers is None:
|
if CONF.workers is None:
|
||||||
# None implies the number of CPUs limited to 8
|
# None implies the number of CPUs limited to 8
|
||||||
# See Launchpad bug #1748916 and the config help text
|
# See Launchpad bug #1748916 and the config help text
|
||||||
@ -740,125 +721,7 @@ class PosixServer(BaseServer):
|
|||||||
self.start_wsgi()
|
self.start_wsgi()
|
||||||
|
|
||||||
|
|
||||||
class Win32ProcessLauncher(object):
|
Server = PosixServer
|
||||||
def __init__(self):
|
|
||||||
self._processutils = os_win_utilsfactory.get_processutils()
|
|
||||||
|
|
||||||
self._workers = []
|
|
||||||
self._worker_job_handles = []
|
|
||||||
|
|
||||||
def add_process(self, cmd):
|
|
||||||
LOG.info("Starting subprocess: %s", cmd)
|
|
||||||
|
|
||||||
worker = subprocess.Popen(cmd, close_fds=False)
|
|
||||||
try:
|
|
||||||
job_handle = self._processutils.kill_process_on_job_close(
|
|
||||||
worker.pid)
|
|
||||||
except Exception:
|
|
||||||
LOG.exception("Could not associate child process "
|
|
||||||
"with a job, killing it.")
|
|
||||||
worker.kill()
|
|
||||||
raise
|
|
||||||
|
|
||||||
self._worker_job_handles.append(job_handle)
|
|
||||||
self._workers.append(worker)
|
|
||||||
|
|
||||||
return worker
|
|
||||||
|
|
||||||
def wait(self):
|
|
||||||
pids = [worker.pid for worker in self._workers]
|
|
||||||
if pids:
|
|
||||||
self._processutils.wait_for_multiple_processes(pids,
|
|
||||||
wait_all=True)
|
|
||||||
# By sleeping here, we allow signal handlers to be executed.
|
|
||||||
time.sleep(0)
|
|
||||||
|
|
||||||
|
|
||||||
class Win32Server(BaseServer):
|
|
||||||
_py_script_re = re.compile(r'.*\.py\w?$')
|
|
||||||
_sock = None
|
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
LOG.warning("Support for Glance on Windows operating systems is"
|
|
||||||
"deprecated.")
|
|
||||||
super(Win32Server, self).__init__(*args, **kwargs)
|
|
||||||
self._launcher = Win32ProcessLauncher()
|
|
||||||
self._ioutils = os_win_utilsfactory.get_ioutils()
|
|
||||||
|
|
||||||
def run_child(self):
|
|
||||||
# We're passing copies of the socket through pipes.
|
|
||||||
rfd, wfd = self._ioutils.create_pipe(inherit_handle=True)
|
|
||||||
|
|
||||||
cmd = sys.argv + ['--pipe-handle=%s' % int(rfd)]
|
|
||||||
# Recent setuptools versions will trim '-script.py' and '.exe'
|
|
||||||
# extensions from sys.argv[0].
|
|
||||||
if self._py_script_re.match(sys.argv[0]):
|
|
||||||
cmd = [sys.executable] + cmd
|
|
||||||
|
|
||||||
worker = self._launcher.add_process(cmd)
|
|
||||||
self._ioutils.close_handle(rfd)
|
|
||||||
|
|
||||||
share_sock_buff = self._sock.share(worker.pid)
|
|
||||||
self._ioutils.write_file(
|
|
||||||
wfd,
|
|
||||||
struct.pack('<I', len(share_sock_buff)),
|
|
||||||
4)
|
|
||||||
self._ioutils.write_file(
|
|
||||||
wfd, share_sock_buff, len(share_sock_buff))
|
|
||||||
|
|
||||||
self.children.add(worker.pid)
|
|
||||||
|
|
||||||
def kill_children(self, *args):
|
|
||||||
# We're using job objects, the children will exit along with the
|
|
||||||
# main process.
|
|
||||||
exit(0)
|
|
||||||
|
|
||||||
def wait_on_children(self):
|
|
||||||
self._launcher.wait()
|
|
||||||
|
|
||||||
def _get_sock_from_parent(self):
|
|
||||||
# This is supposed to be called exactly once in the child process.
|
|
||||||
# We're passing a copy of the socket through a pipe.
|
|
||||||
pipe_handle = int(getattr(CONF, 'pipe_handle', 0))
|
|
||||||
if not pipe_handle:
|
|
||||||
err_msg = _("Did not receive a pipe handle, which is used when "
|
|
||||||
"communicating with the parent process.")
|
|
||||||
raise exception.GlanceException(err_msg)
|
|
||||||
|
|
||||||
# Get the length of the data to be received.
|
|
||||||
buff = self._ioutils.get_buffer(4)
|
|
||||||
self._ioutils.read_file(pipe_handle, buff, 4)
|
|
||||||
socket_buff_sz = struct.unpack('<I', buff)[0]
|
|
||||||
|
|
||||||
# Get the serialized socket object.
|
|
||||||
socket_buff = self._ioutils.get_buffer(socket_buff_sz)
|
|
||||||
self._ioutils.read_file(pipe_handle, socket_buff, socket_buff_sz)
|
|
||||||
self._ioutils.close_handle(pipe_handle)
|
|
||||||
|
|
||||||
# Recreate the socket object. This will only work with
|
|
||||||
# Python 3.6 or later.
|
|
||||||
return socket.fromshare(bytes(socket_buff[:]))
|
|
||||||
|
|
||||||
def configure_socket(self, old_conf=None, has_changed=None):
|
|
||||||
fresh_start = not (old_conf or has_changed)
|
|
||||||
pipe_handle = getattr(CONF, 'pipe_handle', None)
|
|
||||||
|
|
||||||
if not (fresh_start and pipe_handle):
|
|
||||||
return super(Win32Server, self).configure_socket(
|
|
||||||
old_conf, has_changed)
|
|
||||||
|
|
||||||
self.sock = self._get_sock_from_parent()
|
|
||||||
|
|
||||||
if hasattr(socket, 'TCP_KEEPIDLE'):
|
|
||||||
# This was introduced in WS 2016 RS3
|
|
||||||
self.sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE,
|
|
||||||
CONF.tcp_keepidle)
|
|
||||||
|
|
||||||
|
|
||||||
if os.name == 'nt':
|
|
||||||
Server = Win32Server
|
|
||||||
else:
|
|
||||||
Server = PosixServer
|
|
||||||
|
|
||||||
|
|
||||||
class Middleware(object):
|
class Middleware(object):
|
||||||
|
@ -51,7 +51,6 @@ _api_opts = [
|
|||||||
glance.common.wsgi.eventlet_opts,
|
glance.common.wsgi.eventlet_opts,
|
||||||
glance.common.wsgi.socket_opts,
|
glance.common.wsgi.socket_opts,
|
||||||
glance.common.wsgi.store_opts,
|
glance.common.wsgi.store_opts,
|
||||||
glance.common.wsgi.cli_opts,
|
|
||||||
glance.image_cache.drivers.sqlite.sqlite_opts,
|
glance.image_cache.drivers.sqlite.sqlite_opts,
|
||||||
glance.image_cache.image_cache_opts,
|
glance.image_cache.image_cache_opts,
|
||||||
glance.notifier.notifier_opts,
|
glance.notifier.notifier_opts,
|
||||||
|
@ -14,16 +14,9 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import builtins
|
import builtins
|
||||||
import os
|
|
||||||
|
|
||||||
import eventlet
|
import eventlet
|
||||||
|
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()
|
|
||||||
|
|
||||||
import glance.async_
|
import glance.async_
|
||||||
# NOTE(danms): Default to eventlet threading for tests
|
# NOTE(danms): Default to eventlet threading for tests
|
||||||
|
@ -30,7 +30,6 @@ import platform
|
|||||||
import shutil
|
import shutil
|
||||||
import signal
|
import signal
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from testtools import content as ttc
|
from testtools import content as ttc
|
||||||
@ -42,7 +41,6 @@ import uuid
|
|||||||
|
|
||||||
import fixtures
|
import fixtures
|
||||||
import glance_store
|
import glance_store
|
||||||
from os_win import utilsfactory as os_win_utilsfactory
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
import testtools
|
import testtools
|
||||||
@ -58,12 +56,7 @@ 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'
|
||||||
SQLITE_CONN_TEMPLATE = 'sqlite:///%s/tests.sqlite'
|
|
||||||
else:
|
|
||||||
SQLITE_CONN_TEMPLATE = 'sqlite:////%s/tests.sqlite'
|
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
|
|
||||||
@ -301,79 +294,7 @@ class PosixServer(BaseServer):
|
|||||||
return (rc, '', '')
|
return (rc, '', '')
|
||||||
|
|
||||||
|
|
||||||
class Win32Server(BaseServer):
|
Server = PosixServer
|
||||||
def __init__(self, *args, **kwargs):
|
|
||||||
super(Win32Server, self).__init__(*args, **kwargs)
|
|
||||||
|
|
||||||
self._processutils = os_win_utilsfactory.get_processutils()
|
|
||||||
|
|
||||||
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):
|
||||||
|
@ -137,7 +137,6 @@ class TestDriver(test_utils.BaseTestCase):
|
|||||||
def create_images(self, images):
|
def create_images(self, images):
|
||||||
for fixture in images:
|
for fixture in images:
|
||||||
self.db_api.image_create(self.adm_context, fixture)
|
self.db_api.image_create(self.adm_context, fixture)
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
|
|
||||||
|
|
||||||
class DriverTests(object):
|
class DriverTests(object):
|
||||||
@ -318,7 +317,6 @@ class DriverTests(object):
|
|||||||
|
|
||||||
def test_image_update_properties(self):
|
def test_image_update_properties(self):
|
||||||
fixture = {'properties': {'ping': 'pong'}}
|
fixture = {'properties': {'ping': 'pong'}}
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
image = self.db_api.image_update(self.adm_context, UUID1, fixture)
|
image = self.db_api.image_update(self.adm_context, UUID1, fixture)
|
||||||
expected = {'ping': 'pong', 'foo': 'bar', 'far': 'boo'}
|
expected = {'ping': 'pong', 'foo': 'bar', 'far': 'boo'}
|
||||||
actual = {p['name']: p['value'] for p in image['properties']}
|
actual = {p['name']: p['value'] for p in image['properties']}
|
||||||
@ -1294,7 +1292,6 @@ class DriverTests(object):
|
|||||||
'deleted': False}
|
'deleted': False}
|
||||||
self.assertEqual(expected, member)
|
self.assertEqual(expected, member)
|
||||||
|
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
member = self.db_api.image_member_update(self.context,
|
member = self.db_api.image_member_update(self.context,
|
||||||
member_id,
|
member_id,
|
||||||
{'can_share': True})
|
{'can_share': True})
|
||||||
@ -1338,7 +1335,6 @@ class DriverTests(object):
|
|||||||
'deleted': False}
|
'deleted': False}
|
||||||
self.assertEqual(expected, member)
|
self.assertEqual(expected, member)
|
||||||
|
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
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'})
|
||||||
@ -1947,7 +1943,6 @@ class TaskTests(test_utils.BaseTestCase):
|
|||||||
'status': 'processing',
|
'status': 'processing',
|
||||||
'message': 'This is a error string',
|
'message': 'This is a error string',
|
||||||
}
|
}
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
task = self.db_api.task_update(self.adm_context, task_id, fixture)
|
task = self.db_api.task_update(self.adm_context, task_id, fixture)
|
||||||
|
|
||||||
self.assertEqual(task_id, task['id'])
|
self.assertEqual(task_id, task['id'])
|
||||||
@ -1973,7 +1968,6 @@ class TaskTests(test_utils.BaseTestCase):
|
|||||||
|
|
||||||
task_id = task['id']
|
task_id = task['id']
|
||||||
fixture = {'status': 'processing'}
|
fixture = {'status': 'processing'}
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
task = self.db_api.task_update(self.adm_context, task_id, fixture)
|
task = self.db_api.task_update(self.adm_context, task_id, fixture)
|
||||||
|
|
||||||
self.assertEqual(task_id, task['id'])
|
self.assertEqual(task_id, task['id'])
|
||||||
|
@ -351,7 +351,6 @@ class TestCentralizedDb(functional.SynchronousAPIBase):
|
|||||||
|
|
||||||
self.assertTrue(os.path.exists(incomplete_file_path))
|
self.assertTrue(os.path.exists(incomplete_file_path))
|
||||||
|
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
self.driver.clean(stall_time=0)
|
self.driver.clean(stall_time=0)
|
||||||
|
|
||||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||||
|
@ -70,12 +70,6 @@ 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()
|
||||||
|
|
||||||
|
@ -45,18 +45,11 @@ class TestWSGIServer(functional.FunctionalTest):
|
|||||||
port = server.sock.getsockname()[1]
|
port = server.sock.getsockname()[1]
|
||||||
|
|
||||||
def get_request(delay=0.0):
|
def get_request(delay=0.0):
|
||||||
# Socket timeouts are handled rather inconsistently on Windows.
|
sock = socket.socket()
|
||||||
# recv may either return nothing OR raise a ConnectionAbortedError.
|
sock.connect(('127.0.0.1', port))
|
||||||
exp_exc = OSError if os.name == 'nt' else ()
|
time.sleep(delay)
|
||||||
|
sock.send(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
||||||
try:
|
return sock.recv(1024)
|
||||||
sock = socket.socket()
|
|
||||||
sock.connect(('127.0.0.1', port))
|
|
||||||
time.sleep(delay)
|
|
||||||
sock.send(b'GET / HTTP/1.1\r\nHost: localhost\r\n\r\n')
|
|
||||||
return sock.recv(1024)
|
|
||||||
except exp_exc:
|
|
||||||
return None
|
|
||||||
|
|
||||||
# Should succeed - no timeout
|
# Should succeed - no timeout
|
||||||
self.assertIn(greetings, get_request())
|
self.assertIn(greetings, get_request())
|
||||||
|
@ -606,8 +606,6 @@ class ServerTest(test_utils.BaseTestCase):
|
|||||||
def test_number_of_workers_posix(self, mock_migrate_db, mock_prefetcher):
|
def test_number_of_workers_posix(self, mock_migrate_db, mock_prefetcher):
|
||||||
"""Ensure the number of workers matches num cpus limited to 8."""
|
"""Ensure the number of workers matches num cpus limited to 8."""
|
||||||
mock_migrate_db.return_value = False
|
mock_migrate_db.return_value = False
|
||||||
if os.name == 'nt':
|
|
||||||
raise self.skipException("Unsupported platform.")
|
|
||||||
|
|
||||||
def pid():
|
def pid():
|
||||||
i = 1
|
i = 1
|
||||||
|
@ -578,7 +578,6 @@ class TestImageRepo(test_utils.BaseTestCase):
|
|||||||
original_update_time = image.updated_at
|
original_update_time = image.updated_at
|
||||||
image.name = 'foo'
|
image.name = 'foo'
|
||||||
image.tags = ['king', 'kong']
|
image.tags = ['king', 'kong']
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
self.image_repo.save(image)
|
self.image_repo.save(image)
|
||||||
current_update_time = image.updated_at
|
current_update_time = image.updated_at
|
||||||
self.assertGreater(current_update_time, original_update_time)
|
self.assertGreater(current_update_time, original_update_time)
|
||||||
@ -636,7 +635,6 @@ class TestImageRepo(test_utils.BaseTestCase):
|
|||||||
def test_remove_image(self):
|
def test_remove_image(self):
|
||||||
image = self.image_repo.get(UUID1)
|
image = self.image_repo.get(UUID1)
|
||||||
previous_update_time = image.updated_at
|
previous_update_time = image.updated_at
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
self.image_repo.remove(image)
|
self.image_repo.remove(image)
|
||||||
self.assertGreater(image.updated_at, previous_update_time)
|
self.assertGreater(image.updated_at, previous_update_time)
|
||||||
self.assertRaises(exception.ImageNotFound, self.image_repo.get, UUID1)
|
self.assertRaises(exception.ImageNotFound, self.image_repo.get, UUID1)
|
||||||
@ -1053,7 +1051,6 @@ class TestTaskRepo(test_utils.BaseTestCase):
|
|||||||
def test_save_task(self):
|
def test_save_task(self):
|
||||||
task = self.task_repo.get(UUID1)
|
task = self.task_repo.get(UUID1)
|
||||||
original_update_time = task.updated_at
|
original_update_time = task.updated_at
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
self.task_repo.save(task)
|
self.task_repo.save(task)
|
||||||
current_update_time = task.updated_at
|
current_update_time = task.updated_at
|
||||||
self.assertGreater(current_update_time, original_update_time)
|
self.assertGreater(current_update_time, original_update_time)
|
||||||
|
@ -139,7 +139,6 @@ class ImageCacheTestCase(object):
|
|||||||
|
|
||||||
self.assertTrue(os.path.exists(invalid_file_path))
|
self.assertTrue(os.path.exists(invalid_file_path))
|
||||||
|
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
if failure:
|
if failure:
|
||||||
with mock.patch.object(
|
with mock.patch.object(
|
||||||
fileutils, 'delete_if_exists') as mock_delete:
|
fileutils, 'delete_if_exists') as mock_delete:
|
||||||
@ -167,7 +166,6 @@ class ImageCacheTestCase(object):
|
|||||||
|
|
||||||
self.assertTrue(os.path.exists(incomplete_file_path))
|
self.assertTrue(os.path.exists(incomplete_file_path))
|
||||||
|
|
||||||
self.delay_inaccurate_clock()
|
|
||||||
self.cache.clean(stall_time=0)
|
self.cache.clean(stall_time=0)
|
||||||
|
|
||||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||||
|
@ -161,26 +161,6 @@ class BaseTestCase(testtools.TestCase):
|
|||||||
self.addCleanup(patcher.stop)
|
self.addCleanup(patcher.stop)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def delay_inaccurate_clock(self, duration=0.001):
|
|
||||||
"""Add a small delay to compensate for inaccurate system clocks.
|
|
||||||
|
|
||||||
Some tests make assertions based on timestamps (e.g. comparing
|
|
||||||
'created_at' and 'updated_at' fields). In some cases, subsequent
|
|
||||||
time.time() calls may return identical values (python timestamps can
|
|
||||||
have a lower resolution on Windows compared to Linux - 1e-7 as
|
|
||||||
opposed to 1e-9).
|
|
||||||
|
|
||||||
A small delay (a few ms should be negligeable) can prevent such
|
|
||||||
issues. At the same time, it spares us from mocking the time
|
|
||||||
module, which might be undesired.
|
|
||||||
"""
|
|
||||||
|
|
||||||
# For now, we'll do this only for Windows. If really needed,
|
|
||||||
# on Py3 we can get the clock resolution using time.get_clock_info,
|
|
||||||
# but at that point we may as well just sleep 1ms all the time.
|
|
||||||
if os.name == 'nt':
|
|
||||||
time.sleep(duration)
|
|
||||||
|
|
||||||
|
|
||||||
class requires(object):
|
class requires(object):
|
||||||
"""Decorator that initiates additional test setup/teardown."""
|
"""Decorator that initiates additional test setup/teardown."""
|
||||||
@ -209,12 +189,8 @@ class depends_on_exe(object):
|
|||||||
|
|
||||||
def __call__(self, func):
|
def __call__(self, func):
|
||||||
def _runner(*args, **kw):
|
def _runner(*args, **kw):
|
||||||
if os.name != 'nt':
|
exitcode, out, err = execute('which %s' % self.exe,
|
||||||
cmd = 'which %s' % self.exe
|
raise_error=False)
|
||||||
else:
|
|
||||||
cmd = 'where.exe', '%s' % self.exe
|
|
||||||
|
|
||||||
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
|
||||||
args[0].disabled = True
|
args[0].disabled = True
|
||||||
@ -394,10 +370,7 @@ 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
|
||||||
if os.name != 'nt':
|
args = shlex.split(cmd)
|
||||||
args = shlex.split(cmd)
|
|
||||||
else:
|
|
||||||
args = cmd
|
|
||||||
|
|
||||||
executable = args[0]
|
executable = args[0]
|
||||||
if os.path.isabs(executable):
|
if os.path.isabs(executable):
|
||||||
|
5
releasenotes/notes/remove-windows-873b19639c9b6ed5.yaml
Normal file
5
releasenotes/notes/remove-windows-873b19639c9b6ed5.yaml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
upgrade:
|
||||||
|
- |
|
||||||
|
Support for running glance services in Windows operating systems has been
|
||||||
|
removed.
|
@ -51,6 +51,4 @@ cursive>=0.2.1 # Apache-2.0
|
|||||||
# timeutils
|
# timeutils
|
||||||
iso8601>=0.1.11 # MIT
|
iso8601>=0.1.11 # MIT
|
||||||
|
|
||||||
os-win>=4.0.1 # Apache-2.0
|
|
||||||
|
|
||||||
castellan>=0.17.0 # Apache-2.0
|
castellan>=0.17.0 # Apache-2.0
|
||||||
|
Loading…
Reference in New Issue
Block a user