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
|
||||
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
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
@ -1756,8 +1756,7 @@ One main configuration file option affects the image cache.
|
||||
and requires that the filesystem containing ``image_cache_dir`` have
|
||||
access times tracked for all files (in other words, the noatime option
|
||||
CANNOT be set for that filesystem). In addition, ``user_xattr`` must be
|
||||
set on the filesystem's description line in fstab. Because of these
|
||||
requirements, the ``xattr`` cache driver is not available on Windows.
|
||||
set on the filesystem's description line in fstab.
|
||||
|
||||
``image_cache_sqlite_db=DB_FILE``
|
||||
Optional.
|
||||
|
@ -25,13 +25,7 @@ import os
|
||||
import sys
|
||||
|
||||
import eventlet
|
||||
|
||||
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()
|
||||
eventlet.patcher.monkey_patch()
|
||||
|
||||
# Monkey patch the original current_thread to use the up-to-date _active
|
||||
# global variable. See https://bugs.launchpad.net/bugs/1863021 and
|
||||
@ -66,7 +60,6 @@ from glance import version
|
||||
CONF = cfg.CONF
|
||||
CONF.import_group("profiler", "glance.common.wsgi")
|
||||
logging.register_options(CONF)
|
||||
wsgi.register_cli_opts()
|
||||
|
||||
# NOTE(rosmaita): Any new exceptions added should preserve the current
|
||||
# error codes for backward compatibility. The value 99 is returned
|
||||
|
@ -23,13 +23,7 @@ import os
|
||||
import sys
|
||||
|
||||
import eventlet
|
||||
|
||||
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()
|
||||
eventlet.patcher.monkey_patch()
|
||||
|
||||
# Monkey patch the original current_thread to use the up-to-date _active
|
||||
# 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)
|
||||
|
||||
import glance_store
|
||||
from os_win import utilsfactory as os_win_utilsfactory
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
|
||||
@ -64,18 +57,7 @@ CONF.set_default(name='use_stderr', default=True)
|
||||
|
||||
|
||||
def main():
|
||||
# Used on Window, ensuring that a single scrubber can run at a time.
|
||||
mutex = None
|
||||
mutex_acquired = False
|
||||
|
||||
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_opts(scrubber.scrubber_cmd_opts)
|
||||
|
||||
@ -99,12 +81,7 @@ def main():
|
||||
app = scrubber.Scrubber(glance_store)
|
||||
|
||||
if CONF.restore:
|
||||
if os.name == 'nt':
|
||||
scrubber_already_running = not mutex_acquired
|
||||
else:
|
||||
scrubber_already_running = scrubber_already_running_posix()
|
||||
|
||||
if scrubber_already_running:
|
||||
if scrubber_already_running():
|
||||
already_running_msg = (
|
||||
"ERROR: glance-scrubber is already running. "
|
||||
"Please ensure that the daemon is stopped.")
|
||||
@ -121,12 +98,9 @@ def main():
|
||||
sys.exit("ERROR: %s" % e)
|
||||
except RuntimeError as 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.
|
||||
# 1. Try to find the pid file if scrubber is controlled by
|
||||
# glance-control
|
||||
|
@ -24,10 +24,7 @@ import abc
|
||||
import errno
|
||||
import functools
|
||||
import os
|
||||
import re
|
||||
import signal
|
||||
import struct
|
||||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
|
||||
@ -35,7 +32,6 @@ from eventlet.green import socket
|
||||
import eventlet.greenio
|
||||
import eventlet.wsgi
|
||||
import glance_store
|
||||
from os_win import utilsfactory as os_win_utilsfactory
|
||||
from oslo_concurrency import processutils
|
||||
from oslo_config import cfg
|
||||
from oslo_log import log as logging
|
||||
@ -252,13 +248,6 @@ store_opts = [
|
||||
'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__)
|
||||
|
||||
@ -286,17 +275,9 @@ RESERVED_STORES = {
|
||||
}
|
||||
|
||||
|
||||
def register_cli_opts():
|
||||
CONF.register_cli_opts(cli_opts)
|
||||
|
||||
|
||||
def get_num_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:
|
||||
# None implies the number of CPUs limited to 8
|
||||
# See Launchpad bug #1748916 and the config help text
|
||||
@ -740,125 +721,7 @@ class PosixServer(BaseServer):
|
||||
self.start_wsgi()
|
||||
|
||||
|
||||
class Win32ProcessLauncher(object):
|
||||
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
|
||||
Server = PosixServer
|
||||
|
||||
|
||||
class Middleware(object):
|
||||
|
@ -51,7 +51,6 @@ _api_opts = [
|
||||
glance.common.wsgi.eventlet_opts,
|
||||
glance.common.wsgi.socket_opts,
|
||||
glance.common.wsgi.store_opts,
|
||||
glance.common.wsgi.cli_opts,
|
||||
glance.image_cache.drivers.sqlite.sqlite_opts,
|
||||
glance.image_cache.image_cache_opts,
|
||||
glance.notifier.notifier_opts,
|
||||
|
@ -14,16 +14,9 @@
|
||||
# under the License.
|
||||
|
||||
import builtins
|
||||
import os
|
||||
|
||||
import eventlet
|
||||
|
||||
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()
|
||||
eventlet.patcher.monkey_patch()
|
||||
|
||||
import glance.async_
|
||||
# NOTE(danms): Default to eventlet threading for tests
|
||||
|
@ -30,7 +30,6 @@ import platform
|
||||
import shutil
|
||||
import signal
|
||||
import socket
|
||||
import subprocess
|
||||
import sys
|
||||
import tempfile
|
||||
from testtools import content as ttc
|
||||
@ -42,7 +41,6 @@ import uuid
|
||||
|
||||
import fixtures
|
||||
import glance_store
|
||||
from os_win import utilsfactory as os_win_utilsfactory
|
||||
from oslo_config import cfg
|
||||
from oslo_serialization import jsonutils
|
||||
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
|
||||
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'
|
||||
|
||||
|
||||
SQLITE_CONN_TEMPLATE = 'sqlite:////%s/tests.sqlite'
|
||||
CONF = cfg.CONF
|
||||
|
||||
|
||||
@ -301,79 +294,7 @@ class PosixServer(BaseServer):
|
||||
return (rc, '', '')
|
||||
|
||||
|
||||
class Win32Server(BaseServer):
|
||||
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
|
||||
Server = PosixServer
|
||||
|
||||
|
||||
class ApiServer(Server):
|
||||
|
@ -137,7 +137,6 @@ class TestDriver(test_utils.BaseTestCase):
|
||||
def create_images(self, images):
|
||||
for fixture in images:
|
||||
self.db_api.image_create(self.adm_context, fixture)
|
||||
self.delay_inaccurate_clock()
|
||||
|
||||
|
||||
class DriverTests(object):
|
||||
@ -318,7 +317,6 @@ class DriverTests(object):
|
||||
|
||||
def test_image_update_properties(self):
|
||||
fixture = {'properties': {'ping': 'pong'}}
|
||||
self.delay_inaccurate_clock()
|
||||
image = self.db_api.image_update(self.adm_context, UUID1, fixture)
|
||||
expected = {'ping': 'pong', 'foo': 'bar', 'far': 'boo'}
|
||||
actual = {p['name']: p['value'] for p in image['properties']}
|
||||
@ -1294,7 +1292,6 @@ class DriverTests(object):
|
||||
'deleted': False}
|
||||
self.assertEqual(expected, member)
|
||||
|
||||
self.delay_inaccurate_clock()
|
||||
member = self.db_api.image_member_update(self.context,
|
||||
member_id,
|
||||
{'can_share': True})
|
||||
@ -1338,7 +1335,6 @@ class DriverTests(object):
|
||||
'deleted': False}
|
||||
self.assertEqual(expected, member)
|
||||
|
||||
self.delay_inaccurate_clock()
|
||||
member = self.db_api.image_member_update(self.context,
|
||||
member_id,
|
||||
{'status': 'accepted'})
|
||||
@ -1947,7 +1943,6 @@ class TaskTests(test_utils.BaseTestCase):
|
||||
'status': 'processing',
|
||||
'message': 'This is a error string',
|
||||
}
|
||||
self.delay_inaccurate_clock()
|
||||
task = self.db_api.task_update(self.adm_context, task_id, fixture)
|
||||
|
||||
self.assertEqual(task_id, task['id'])
|
||||
@ -1973,7 +1968,6 @@ class TaskTests(test_utils.BaseTestCase):
|
||||
|
||||
task_id = task['id']
|
||||
fixture = {'status': 'processing'}
|
||||
self.delay_inaccurate_clock()
|
||||
task = self.db_api.task_update(self.adm_context, task_id, fixture)
|
||||
|
||||
self.assertEqual(task_id, task['id'])
|
||||
|
@ -351,7 +351,6 @@ class TestCentralizedDb(functional.SynchronousAPIBase):
|
||||
|
||||
self.assertTrue(os.path.exists(incomplete_file_path))
|
||||
|
||||
self.delay_inaccurate_clock()
|
||||
self.driver.clean(stall_time=0)
|
||||
|
||||
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
|
||||
"""
|
||||
|
||||
# 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.start_servers()
|
||||
|
||||
|
@ -45,18 +45,11 @@ class TestWSGIServer(functional.FunctionalTest):
|
||||
port = server.sock.getsockname()[1]
|
||||
|
||||
def get_request(delay=0.0):
|
||||
# Socket timeouts are handled rather inconsistently on Windows.
|
||||
# recv may either return nothing OR raise a ConnectionAbortedError.
|
||||
exp_exc = OSError if os.name == 'nt' else ()
|
||||
|
||||
try:
|
||||
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
|
||||
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)
|
||||
|
||||
# Should succeed - no timeout
|
||||
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):
|
||||
"""Ensure the number of workers matches num cpus limited to 8."""
|
||||
mock_migrate_db.return_value = False
|
||||
if os.name == 'nt':
|
||||
raise self.skipException("Unsupported platform.")
|
||||
|
||||
def pid():
|
||||
i = 1
|
||||
|
@ -578,7 +578,6 @@ class TestImageRepo(test_utils.BaseTestCase):
|
||||
original_update_time = image.updated_at
|
||||
image.name = 'foo'
|
||||
image.tags = ['king', 'kong']
|
||||
self.delay_inaccurate_clock()
|
||||
self.image_repo.save(image)
|
||||
current_update_time = image.updated_at
|
||||
self.assertGreater(current_update_time, original_update_time)
|
||||
@ -636,7 +635,6 @@ class TestImageRepo(test_utils.BaseTestCase):
|
||||
def test_remove_image(self):
|
||||
image = self.image_repo.get(UUID1)
|
||||
previous_update_time = image.updated_at
|
||||
self.delay_inaccurate_clock()
|
||||
self.image_repo.remove(image)
|
||||
self.assertGreater(image.updated_at, previous_update_time)
|
||||
self.assertRaises(exception.ImageNotFound, self.image_repo.get, UUID1)
|
||||
@ -1053,7 +1051,6 @@ class TestTaskRepo(test_utils.BaseTestCase):
|
||||
def test_save_task(self):
|
||||
task = self.task_repo.get(UUID1)
|
||||
original_update_time = task.updated_at
|
||||
self.delay_inaccurate_clock()
|
||||
self.task_repo.save(task)
|
||||
current_update_time = task.updated_at
|
||||
self.assertGreater(current_update_time, original_update_time)
|
||||
|
@ -139,7 +139,6 @@ class ImageCacheTestCase(object):
|
||||
|
||||
self.assertTrue(os.path.exists(invalid_file_path))
|
||||
|
||||
self.delay_inaccurate_clock()
|
||||
if failure:
|
||||
with mock.patch.object(
|
||||
fileutils, 'delete_if_exists') as mock_delete:
|
||||
@ -167,7 +166,6 @@ class ImageCacheTestCase(object):
|
||||
|
||||
self.assertTrue(os.path.exists(incomplete_file_path))
|
||||
|
||||
self.delay_inaccurate_clock()
|
||||
self.cache.clean(stall_time=0)
|
||||
|
||||
self.assertFalse(os.path.exists(incomplete_file_path))
|
||||
|
@ -161,26 +161,6 @@ class BaseTestCase(testtools.TestCase):
|
||||
self.addCleanup(patcher.stop)
|
||||
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):
|
||||
"""Decorator that initiates additional test setup/teardown."""
|
||||
@ -209,12 +189,8 @@ class depends_on_exe(object):
|
||||
|
||||
def __call__(self, func):
|
||||
def _runner(*args, **kw):
|
||||
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('which %s' % self.exe,
|
||||
raise_error=False)
|
||||
if exitcode != 0:
|
||||
args[0].disabled_message = 'test requires exe: %s' % self.exe
|
||||
args[0].disabled = True
|
||||
@ -394,10 +370,7 @@ def execute(cmd,
|
||||
path_ext = [os.path.join(os.getcwd(), 'bin')]
|
||||
|
||||
# Also jack in the path cmd comes from, if it's absolute
|
||||
if os.name != 'nt':
|
||||
args = shlex.split(cmd)
|
||||
else:
|
||||
args = cmd
|
||||
args = shlex.split(cmd)
|
||||
|
||||
executable = args[0]
|
||||
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
|
||||
iso8601>=0.1.11 # MIT
|
||||
|
||||
os-win>=4.0.1 # Apache-2.0
|
||||
|
||||
castellan>=0.17.0 # Apache-2.0
|
||||
|
Loading…
Reference in New Issue
Block a user