Add python-troveclient in requirements.txt
Change-Id: I2bd0d81171df85c05423e19ab2e4afa82fcf880e
This commit is contained in:
parent
ae2709dcd6
commit
7d78c74158
@ -64,7 +64,6 @@
|
|||||||
required-projects:
|
required-projects:
|
||||||
- openstack/devstack-gate
|
- openstack/devstack-gate
|
||||||
- openstack/diskimage-builder
|
- openstack/diskimage-builder
|
||||||
- openstack/python-troveclient
|
|
||||||
- openstack/tripleo-image-elements
|
- openstack/tripleo-image-elements
|
||||||
- openstack/trove
|
- openstack/trove
|
||||||
- openstack/trove-dashboard
|
- openstack/trove-dashboard
|
||||||
@ -85,7 +84,6 @@
|
|||||||
required-projects:
|
required-projects:
|
||||||
- openstack/tempest
|
- openstack/tempest
|
||||||
- openstack/diskimage-builder
|
- openstack/diskimage-builder
|
||||||
- openstack/python-troveclient
|
|
||||||
- openstack/tripleo-image-elements
|
- openstack/tripleo-image-elements
|
||||||
- openstack/trove
|
- openstack/trove
|
||||||
- openstack/trove-dashboard
|
- openstack/trove-dashboard
|
||||||
@ -328,7 +326,6 @@
|
|||||||
parent: devstack-tempest
|
parent: devstack-tempest
|
||||||
timeout: 7800
|
timeout: 7800
|
||||||
required-projects: &base_required_projects
|
required-projects: &base_required_projects
|
||||||
- openstack/python-troveclient
|
|
||||||
- openstack/trove
|
- openstack/trove
|
||||||
- openstack/trove-tempest-plugin
|
- openstack/trove-tempest-plugin
|
||||||
- openstack/tempest
|
- openstack/tempest
|
||||||
|
@ -17,27 +17,12 @@ REQUIREMENTS_FILE=${TROVESTACK_SCRIPTS}/../../requirements.txt
|
|||||||
|
|
||||||
sudo -Hiu ${HOST_USERNAME} dd if=${REQUIREMENTS_FILE} of=${TMP_HOOKS_PATH}/requirements.txt
|
sudo -Hiu ${HOST_USERNAME} dd if=${REQUIREMENTS_FILE} of=${TMP_HOOKS_PATH}/requirements.txt
|
||||||
|
|
||||||
# Grab the upper constraints file, but don't fail if we can't find it.
|
|
||||||
# If we are running in the CI environment, $DEST will be set and stackrc
|
|
||||||
# will use $DEST/requirements as the location for the requirements repo.
|
|
||||||
# Use that as it will help us chain a job with something that is changing UC.
|
|
||||||
|
|
||||||
UC_FILE=upper-constraints.txt
|
UC_FILE=upper-constraints.txt
|
||||||
|
UC_DIR=$(pwd)
|
||||||
|
UC_BRANCH=${TROVE_BRANCH##stable/}
|
||||||
|
|
||||||
if [ -f "${DEST}/requirements/${UC_FILE}" ]; then
|
curl -L -o "${UC_DIR}/${UC_FILE}" "https://releases.openstack.org/constraints/upper/${UC_BRANCH}"
|
||||||
echo "Found ${DEST}/requirements/${UC_FILE}, using that"
|
if [ -f "${UC_DIR}/${UC_FILE}" ]; then
|
||||||
sudo -Hiu ${HOST_USERNAME} dd if="${DEST}/requirements/${UC_FILE}" \
|
sudo -Hiu ${HOST_USERNAME} dd if="${UC_DIR}/${UC_FILE}" of=${TMP_HOOKS_PATH}/${UC_FILE}
|
||||||
of="${TMP_HOOKS_PATH}/${UC_FILE}"
|
rm -f "${UC_DIR}/${UC_FILE}"
|
||||||
else
|
|
||||||
UC_DIR=$(pwd)
|
|
||||||
UC_BRANCH=${TROVE_BRANCH##stable/}
|
|
||||||
|
|
||||||
set +e
|
|
||||||
curl -L -o "${UC_DIR}/${UC_FILE}" "https://releases.openstack.org/constraints/upper/${UC_BRANCH}"
|
|
||||||
set -e
|
|
||||||
|
|
||||||
if [ -f "${UC_DIR}/${UC_FILE}" ]; then
|
|
||||||
sudo -Hiu ${HOST_USERNAME} dd if="${UC_DIR}/${UC_FILE}" of=${TMP_HOOKS_PATH}/${UC_FILE}
|
|
||||||
rm -f "${UC_DIR}/${UC_FILE}"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
|
@ -188,8 +188,6 @@ function dump_env() {
|
|||||||
done
|
done
|
||||||
exclaim "Dumping pip modules:"
|
exclaim "Dumping pip modules:"
|
||||||
pip freeze | sort
|
pip freeze | sort
|
||||||
exclaim "Dumping domain list:"
|
|
||||||
openstack --os-cloud=devstack-admin domain list
|
|
||||||
exclaim "Dumping configuration completed"
|
exclaim "Dumping configuration completed"
|
||||||
set -e
|
set -e
|
||||||
fi
|
fi
|
||||||
@ -764,6 +762,10 @@ function cmd_test_init() {
|
|||||||
|
|
||||||
exclaim "Creating Test Flavors."
|
exclaim "Creating Test Flavors."
|
||||||
add_test_flavors
|
add_test_flavors
|
||||||
|
|
||||||
|
exclaim "Re-installing python-troveclient from git"
|
||||||
|
pip3 uninstall -y python-troveclient
|
||||||
|
pip3 install -U git+https://opendev.org/openstack/python-troveclient@master#egg=python-troveclient
|
||||||
}
|
}
|
||||||
|
|
||||||
function cmd_build_image() {
|
function cmd_build_image() {
|
||||||
@ -1207,8 +1209,9 @@ function cmd_kick_start() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
exclaim "Running kick-start for $DATASTORE_TYPE"
|
exclaim "Running kick-start for $DATASTORE_TYPE"
|
||||||
dump_env
|
|
||||||
cmd_test_init "${DATASTORE_TYPE}" "${DATASTORE_VERSION}"
|
cmd_test_init "${DATASTORE_TYPE}" "${DATASTORE_VERSION}"
|
||||||
|
|
||||||
|
dump_env
|
||||||
}
|
}
|
||||||
|
|
||||||
# Start functional test. The guest image should be created and registered in
|
# Start functional test. The guest image should be created and registered in
|
||||||
|
@ -22,6 +22,7 @@ python-swiftclient>=3.2.0 # Apache-2.0
|
|||||||
python-designateclient>=2.7.0 # Apache-2.0
|
python-designateclient>=2.7.0 # Apache-2.0
|
||||||
python-neutronclient>=6.7.0 # Apache-2.0
|
python-neutronclient>=6.7.0 # Apache-2.0
|
||||||
python-glanceclient>=2.8.0 # Apache-2.0
|
python-glanceclient>=2.8.0 # Apache-2.0
|
||||||
|
python-troveclient>=2.2.0 # Apache-2.0
|
||||||
iso8601>=0.1.11 # MIT
|
iso8601>=0.1.11 # MIT
|
||||||
jsonschema>=2.6.0 # MIT
|
jsonschema>=2.6.0 # MIT
|
||||||
Jinja2>=2.10 # BSD License (3 clause)
|
Jinja2>=2.10 # BSD License (3 clause)
|
||||||
|
@ -1 +0,0 @@
|
|||||||
git+https://opendev.org/openstack/python-troveclient@master#egg=python-troveclient
|
|
3
tox.ini
3
tox.ini
@ -13,7 +13,6 @@ setenv = VIRTUAL_ENV={envdir}
|
|||||||
|
|
||||||
usedevelop = True
|
usedevelop = True
|
||||||
install_command = pip install \
|
install_command = pip install \
|
||||||
-c{env:TEST_UPPER_CONSTRAINTS_FILE:{toxinidir}/test-upper-constraints.txt} \
|
|
||||||
-c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} \
|
-c{env:UPPER_CONSTRAINTS_FILE:https://opendev.org/openstack/requirements/raw/branch/master/upper-constraints.txt} \
|
||||||
-U {opts} {packages}
|
-U {opts} {packages}
|
||||||
deps = -r{toxinidir}/requirements.txt
|
deps = -r{toxinidir}/requirements.txt
|
||||||
@ -56,7 +55,7 @@ ignore-path = .venv,.tox,.git,dist,doc,*egg-info,tools,etc,build,*.po,*.pot,inte
|
|||||||
show-source = True
|
show-source = True
|
||||||
# H301 is ignored on purpose.
|
# H301 is ignored on purpose.
|
||||||
# The rest of the ignores are TODOs.
|
# The rest of the ignores are TODOs.
|
||||||
ignore = F821,H301,H404,H405,H501,E402,W503,E731
|
ignore = E402,E731,F601,F821,H301,H404,H405,H501,W503,W504,W605
|
||||||
enable-extensions = H203,H106
|
enable-extensions = H203,H106
|
||||||
builtins = _
|
builtins = _
|
||||||
# add *.yaml for playbooks/trove-devstack-base.yaml, as it will be matched by
|
# add *.yaml for playbooks/trove-devstack-base.yaml, as it will be matched by
|
||||||
|
@ -146,6 +146,7 @@ class Limit(object):
|
|||||||
"resetTime": int(self.next_request or self._get_time()),
|
"resetTime": int(self.next_request or self._get_time()),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
# "Limit" format is a dictionary with the HTTP verb, human-readable URI,
|
# "Limit" format is a dictionary with the HTTP verb, human-readable URI,
|
||||||
# a regular-expression to match, value and unit of measure (PER_DAY, etc.)
|
# a regular-expression to match, value and unit of measure (PER_DAY, etc.)
|
||||||
DEFAULT_LIMITS = [
|
DEFAULT_LIMITS = [
|
||||||
|
@ -58,6 +58,7 @@ def build_jinja_environment():
|
|||||||
env.globals['min'] = min
|
env.globals['min'] = min
|
||||||
return env
|
return env
|
||||||
|
|
||||||
|
|
||||||
ENV = build_jinja_environment()
|
ENV = build_jinja_environment()
|
||||||
|
|
||||||
|
|
||||||
|
@ -85,4 +85,5 @@ class Queryable(object):
|
|||||||
return lambda model, **conditions: Query(
|
return lambda model, **conditions: Query(
|
||||||
model, query_func=getattr(get_db_api(), item), **conditions)
|
model, query_func=getattr(get_db_api(), item), **conditions)
|
||||||
|
|
||||||
|
|
||||||
db_query = Queryable()
|
db_query = Queryable()
|
||||||
|
@ -34,7 +34,7 @@ class Flavor(object):
|
|||||||
try:
|
try:
|
||||||
client = create_nova_client(context)
|
client = create_nova_client(context)
|
||||||
self.flavor = client.flavors.get(flavor_id)
|
self.flavor = client.flavors.get(flavor_id)
|
||||||
except nova_exceptions.NotFound as e:
|
except nova_exceptions.NotFound:
|
||||||
raise exception.NotFound(uuid=flavor_id)
|
raise exception.NotFound(uuid=flavor_id)
|
||||||
except nova_exceptions.ClientException as e:
|
except nova_exceptions.ClientException as e:
|
||||||
raise exception.TroveError(str(e))
|
raise exception.TroveError(str(e))
|
||||||
|
@ -419,8 +419,8 @@ class SetServerVariable(object):
|
|||||||
else:
|
else:
|
||||||
return "SET GLOBAL %s=%s" % (self.key, self.value)
|
return "SET GLOBAL %s=%s" % (self.key, self.value)
|
||||||
|
|
||||||
# Miscellaneous queries that need no parameters.
|
|
||||||
|
|
||||||
|
# Miscellaneous queries that need no parameters.
|
||||||
FLUSH = "FLUSH PRIVILEGES;"
|
FLUSH = "FLUSH PRIVILEGES;"
|
||||||
ROOT_ENABLED = ("SELECT User FROM mysql.user "
|
ROOT_ENABLED = ("SELECT User FROM mysql.user "
|
||||||
"WHERE User = 'root' AND Host != 'localhost';")
|
"WHERE User = 'root' AND Host != 'localhost';")
|
||||||
|
@ -229,7 +229,7 @@ class CouchDBAdmin(object):
|
|||||||
'username': user.name,
|
'username': user.name,
|
||||||
'password': user.password},
|
'password': user.password},
|
||||||
shell=True)
|
shell=True)
|
||||||
except exception.ProcessExecutionError as pe:
|
except exception.ProcessExecutionError:
|
||||||
LOG.exception("Error creating user: %s.", user.name)
|
LOG.exception("Error creating user: %s.", user.name)
|
||||||
|
|
||||||
for database in user.databases:
|
for database in user.databases:
|
||||||
|
@ -451,7 +451,7 @@ class DB2Admin(object):
|
|||||||
system.CREATE_USER_COMMAND % {
|
system.CREATE_USER_COMMAND % {
|
||||||
'login': user.name, 'login': user.name,
|
'login': user.name, 'login': user.name,
|
||||||
'passwd': user.password}, shell=True)
|
'passwd': user.password}, shell=True)
|
||||||
except exception.ProcessExecutionError as pe:
|
except exception.ProcessExecutionError:
|
||||||
LOG.exception("Error creating user: %s.", user.name)
|
LOG.exception("Error creating user: %s.", user.name)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -495,7 +495,7 @@ class DB2Admin(object):
|
|||||||
LOG.debug("Revoked access for user:%(user)s on "
|
LOG.debug("Revoked access for user:%(user)s on "
|
||||||
"database:%(db)s.",
|
"database:%(db)s.",
|
||||||
{'user': userName, 'db': mydb.name})
|
{'user': userName, 'db': mydb.name})
|
||||||
except exception.ProcessExecutionError as pe:
|
except exception.ProcessExecutionError:
|
||||||
LOG.debug("Error occurred while revoking access to %s.",
|
LOG.debug("Error occurred while revoking access to %s.",
|
||||||
mydb.name)
|
mydb.name)
|
||||||
try:
|
try:
|
||||||
|
@ -32,6 +32,6 @@ REDIS_PACKAGE = ''
|
|||||||
SERVICE_CANDIDATES = ['redis-server', 'redis']
|
SERVICE_CANDIDATES = ['redis-server', 'redis']
|
||||||
|
|
||||||
OS = get_os()
|
OS = get_os()
|
||||||
if OS is 'redhat':
|
if OS == 'redhat':
|
||||||
REDIS_CONFIG = '/etc/redis.conf'
|
REDIS_CONFIG = '/etc/redis.conf'
|
||||||
REDIS_PACKAGE = 'redis'
|
REDIS_PACKAGE = 'redis'
|
||||||
|
@ -122,5 +122,6 @@ class InstanceTasks(object):
|
|||||||
'Build error: Port.',
|
'Build error: Port.',
|
||||||
is_error=True)
|
is_error=True)
|
||||||
|
|
||||||
|
|
||||||
# Dissuade further additions at run-time.
|
# Dissuade further additions at run-time.
|
||||||
InstanceTask.__init__ = None
|
InstanceTask.__init__ = None
|
||||||
|
@ -566,13 +566,13 @@ class FreshInstanceTasks(FreshInstance, NotifyMixin, ConfigurationMixin):
|
|||||||
|
|
||||||
backup_info = None
|
backup_info = None
|
||||||
if backup_id is not None:
|
if backup_id is not None:
|
||||||
backup = bkup_models.Backup.get_by_id(self.context, backup_id)
|
backup = bkup_models.Backup.get_by_id(self.context, backup_id)
|
||||||
backup_info = {'id': backup_id,
|
backup_info = {'id': backup_id,
|
||||||
'instance_id': backup.instance_id,
|
'instance_id': backup.instance_id,
|
||||||
'location': backup.location,
|
'location': backup.location,
|
||||||
'type': backup.backup_type,
|
'type': backup.backup_type,
|
||||||
'checksum': backup.checksum,
|
'checksum': backup.checksum,
|
||||||
}
|
}
|
||||||
self._guest_prepare(flavor['ram'], volume_info,
|
self._guest_prepare(flavor['ram'], volume_info,
|
||||||
packages, databases, users, backup_info,
|
packages, databases, users, backup_info,
|
||||||
config.config_contents, root_password,
|
config.config_contents, root_password,
|
||||||
|
@ -183,35 +183,35 @@ def make_client(user):
|
|||||||
|
|
||||||
def write_snippet(get_replace_list, client, name, url, method, status, reason,
|
def write_snippet(get_replace_list, client, name, url, method, status, reason,
|
||||||
func, *func_args):
|
func, *func_args):
|
||||||
"""
|
"""
|
||||||
'name' is the name of the file, while 'url,' 'method,' 'status,'
|
'name' is the name of the file, while 'url,' 'method,' 'status,'
|
||||||
and 'reason' are expected values that are asserted against.
|
and 'reason' are expected values that are asserted against.
|
||||||
If func_args is present, it is a list of lists, each one of which
|
If func_args is present, it is a list of lists, each one of which
|
||||||
is passed as the *args to the two invocations of "func".
|
is passed as the *args to the two invocations of "func".
|
||||||
"""
|
"""
|
||||||
func_args = func_args or []
|
func_args = func_args or []
|
||||||
snippet_writer = SnippetWriter(conf, get_replace_list)
|
snippet_writer = SnippetWriter(conf, get_replace_list)
|
||||||
results = []
|
results = []
|
||||||
client.client.snippet_writer = snippet_writer
|
client.client.snippet_writer = snippet_writer
|
||||||
client.client.name = name
|
client.client.name = name
|
||||||
args = func_args
|
args = func_args
|
||||||
result = func(client, *args)
|
result = func(client, *args)
|
||||||
|
|
||||||
# Now write the snippet (if this happens earlier we can't replace
|
# Now write the snippet (if this happens earlier we can't replace
|
||||||
# data such as the instance ID).
|
# data such as the instance ID).
|
||||||
client.client.write_snippet()
|
client.client.write_snippet()
|
||||||
with Check() as check:
|
with Check() as check:
|
||||||
check.equal(client.client.old_info['url'], url)
|
check.equal(client.client.old_info['url'], url)
|
||||||
check.equal(client.client.old_info['method'], method)
|
check.equal(client.client.old_info['method'], method)
|
||||||
check.equal(client.client.old_info['response_headers'].status,
|
check.equal(client.client.old_info['response_headers'].status,
|
||||||
status)
|
status)
|
||||||
check.equal(client.client.old_info['response_headers'].reason,
|
check.equal(client.client.old_info['response_headers'].reason,
|
||||||
reason)
|
reason)
|
||||||
results.append(result)
|
results.append(result)
|
||||||
# To prevent this from writing a snippet somewhere else...
|
# To prevent this from writing a snippet somewhere else...
|
||||||
client.client.name = "junk"
|
client.client.name = "junk"
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
|
||||||
JSON_INDEX = 0
|
JSON_INDEX = 0
|
||||||
|
@ -92,9 +92,9 @@ class FakeGuest(object):
|
|||||||
LOG.debug("Updating attributes")
|
LOG.debug("Updating attributes")
|
||||||
self._check_username(username)
|
self._check_username(username)
|
||||||
if (username, hostname) not in self.users:
|
if (username, hostname) not in self.users:
|
||||||
raise rd_exception.UserNotFound(
|
raise rd_exception.UserNotFound(
|
||||||
"User %s@%s cannot be found on the instance."
|
"User %s@%s cannot be found on the instance."
|
||||||
% (username, hostname))
|
% (username, hostname))
|
||||||
new_name = user_attrs.get('name')
|
new_name = user_attrs.get('name')
|
||||||
new_host = user_attrs.get('host')
|
new_host = user_attrs.get('host')
|
||||||
new_password = user_attrs.get('password')
|
new_password = user_attrs.get('password')
|
||||||
|
@ -307,36 +307,38 @@ class ParseLimitsTest(BaseLimitTestSuite):
|
|||||||
def test_multiple_rules(self):
|
def test_multiple_rules(self):
|
||||||
# Test that parse_limits() handles multiple rules correctly.
|
# Test that parse_limits() handles multiple rules correctly.
|
||||||
try:
|
try:
|
||||||
l = limits.Limiter.parse_limits('(get, *, .*, 20, minute);'
|
result = limits.Limiter.parse_limits(
|
||||||
'(PUT, /foo*, /foo.*, 10, hour);'
|
'(get, *, .*, 20, minute);'
|
||||||
'(POST, /bar*, /bar.*, 5, second);'
|
'(PUT, /foo*, /foo.*, 10, hour);'
|
||||||
'(Say, /derp*, /derp.*, 1, day)')
|
'(POST, /bar*, /bar.*, 5, second);'
|
||||||
|
'(Say, /derp*, /derp.*, 1, day)'
|
||||||
|
)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
assert False, str(e)
|
assert False, str(e)
|
||||||
|
|
||||||
# Make sure the number of returned limits are correct
|
# Make sure the number of returned limits are correct
|
||||||
self.assertEqual(4, len(l))
|
self.assertEqual(4, len(result))
|
||||||
|
|
||||||
# Check all the verbs...
|
# Check all the verbs...
|
||||||
expected = ['GET', 'PUT', 'POST', 'SAY']
|
expected = ['GET', 'PUT', 'POST', 'SAY']
|
||||||
self.assertEqual(expected, [t.verb for t in l])
|
self.assertEqual(expected, [t.verb for t in result])
|
||||||
|
|
||||||
# ...the URIs...
|
# ...the URIs...
|
||||||
expected = ['*', '/foo*', '/bar*', '/derp*']
|
expected = ['*', '/foo*', '/bar*', '/derp*']
|
||||||
self.assertEqual(expected, [t.uri for t in l])
|
self.assertEqual(expected, [t.uri for t in result])
|
||||||
|
|
||||||
# ...the regexes...
|
# ...the regexes...
|
||||||
expected = ['.*', '/foo.*', '/bar.*', '/derp.*']
|
expected = ['.*', '/foo.*', '/bar.*', '/derp.*']
|
||||||
self.assertEqual(expected, [t.regex for t in l])
|
self.assertEqual(expected, [t.regex for t in result])
|
||||||
|
|
||||||
# ...the values...
|
# ...the values...
|
||||||
expected = [20, 10, 5, 1]
|
expected = [20, 10, 5, 1]
|
||||||
self.assertEqual(expected, [t.value for t in l])
|
self.assertEqual(expected, [t.value for t in result])
|
||||||
|
|
||||||
# ...and the units...
|
# ...and the units...
|
||||||
expected = [limits.PER_MINUTE, limits.PER_HOUR,
|
expected = [limits.PER_MINUTE, limits.PER_HOUR,
|
||||||
limits.PER_SECOND, limits.PER_DAY]
|
limits.PER_SECOND, limits.PER_DAY]
|
||||||
self.assertEqual(expected, [t.unit for t in l])
|
self.assertEqual(expected, [t.unit for t in result])
|
||||||
|
|
||||||
|
|
||||||
class LimiterTest(BaseLimitTestSuite):
|
class LimiterTest(BaseLimitTestSuite):
|
||||||
|
@ -37,6 +37,7 @@ def _prep_conf(current_time):
|
|||||||
instance_id = 'INSTANCE-' + current_time
|
instance_id = 'INSTANCE-' + current_time
|
||||||
return _context, instance_id
|
return _context, instance_id
|
||||||
|
|
||||||
|
|
||||||
BACKUP_NAME = 'WORKS'
|
BACKUP_NAME = 'WORKS'
|
||||||
BACKUP_NAME_2 = 'IT-WORKS'
|
BACKUP_NAME_2 = 'IT-WORKS'
|
||||||
BACKUP_NAME_3 = 'SECOND-LAST-ONE'
|
BACKUP_NAME_3 = 'SECOND-LAST-ONE'
|
||||||
|
@ -181,6 +181,7 @@ class Coroutine(object):
|
|||||||
self.my_sem.release()
|
self.my_sem.release()
|
||||||
self.caller_sem.acquire() # Wait for it to finish.
|
self.caller_sem.acquire() # Wait for it to finish.
|
||||||
|
|
||||||
|
|
||||||
# Main global thread to run.
|
# Main global thread to run.
|
||||||
main_greenlet = None
|
main_greenlet = None
|
||||||
|
|
||||||
@ -238,7 +239,7 @@ def fake_poll_until(retriever, condition=lambda value: value,
|
|||||||
fake_sleep(sleep_time)
|
fake_sleep(sleep_time)
|
||||||
slept_time += sleep_time
|
slept_time += sleep_time
|
||||||
if time_out and slept_time >= time_out:
|
if time_out and slept_time >= time_out:
|
||||||
raise exception.PollTimeOut()
|
raise exception.PollTimeOut()
|
||||||
|
|
||||||
|
|
||||||
def run_main(func):
|
def run_main(func):
|
||||||
|
Loading…
Reference in New Issue
Block a user