fix tox python3 overrides
We want to default to running all tox environments under python 3, so set the basepython value in each environment. We do not want to specify a minor version number, because we do not want to have to update the file every time we upgrade python. We do not want to set the override once in testenv, because that breaks the more specific versions used in default environments like py35 and py36. This patch also updates pylint to 1.5.6 which is compatible with python3. In updating pylint we have some issues to correct, this patch addresses those issues so the Octavia code passes pylint 1.5.6. Change-Id: Iec21f4c803a427059d595612336d67a35ebf9585 Signed-off-by: Doug Hellmann <doug@doughellmann.com>
This commit is contained in:
parent
3d545ab1b6
commit
0322cbc5c3
|
@ -51,7 +51,11 @@ disable=
|
||||||
too-many-locals,
|
too-many-locals,
|
||||||
too-many-public-methods,
|
too-many-public-methods,
|
||||||
too-many-return-statements,
|
too-many-return-statements,
|
||||||
too-many-statements
|
too-many-statements,
|
||||||
|
multiple-statements,
|
||||||
|
duplicate-except,
|
||||||
|
keyword-arg-before-vararg,
|
||||||
|
deprecated-method
|
||||||
|
|
||||||
[BASIC]
|
[BASIC]
|
||||||
# Variable names can be 1 to 31 characters long, with lowercase and underscores
|
# Variable names can be 1 to 31 characters long, with lowercase and underscores
|
||||||
|
@ -80,8 +84,6 @@ max-line-length=79
|
||||||
additional-builtins=
|
additional-builtins=
|
||||||
|
|
||||||
[CLASSES]
|
[CLASSES]
|
||||||
# List of interface methods to ignore, separated by a comma.
|
|
||||||
ignore-iface-methods=
|
|
||||||
|
|
||||||
[IMPORTS]
|
[IMPORTS]
|
||||||
# Deprecated modules which should not be used, separated by a comma
|
# Deprecated modules which should not be used, separated by a comma
|
||||||
|
@ -94,4 +96,3 @@ ignored-modules=six.moves,_MovedItems
|
||||||
[REPORTS]
|
[REPORTS]
|
||||||
# Tells whether to display a full report or only the messages
|
# Tells whether to display a full report or only the messages
|
||||||
reports=no
|
reports=no
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
# Docs
|
# Docs
|
||||||
os-api-ref>=1.4.0 # Apache-2.0
|
os-api-ref>=1.4.0 # Apache-2.0
|
||||||
sphinxcontrib-actdiag>=0.8.5 # BSD
|
sphinxcontrib-actdiag>=0.8.5 # BSD
|
||||||
sphinxcontrib-apidoc # BSD
|
sphinxcontrib-apidoc>=0.2.1 # BSD
|
||||||
sphinxcontrib-blockdiag>=1.5.4 # BSD
|
sphinxcontrib-blockdiag>=1.5.4 # BSD
|
||||||
sphinxcontrib-nwdiag>=0.9.5 # BSD
|
sphinxcontrib-nwdiag>=0.9.5 # BSD
|
||||||
sphinxcontrib-seqdiag>=0.8.4 # BSD
|
sphinxcontrib-seqdiag>=0.8.4 # BSD
|
||||||
|
|
|
@ -109,7 +109,7 @@ pycparser==2.18
|
||||||
pyflakes==1.0.0
|
pyflakes==1.0.0
|
||||||
Pygments==2.2.0
|
Pygments==2.2.0
|
||||||
pyinotify==0.9.6
|
pyinotify==0.9.6
|
||||||
pylint==1.4.5
|
pylint==1.9.2
|
||||||
PyMySQL==0.7.6
|
PyMySQL==0.7.6
|
||||||
PyNaCl==1.2.1
|
PyNaCl==1.2.1
|
||||||
pyOpenSSL==17.1.0
|
pyOpenSSL==17.1.0
|
||||||
|
|
|
@ -18,6 +18,7 @@ import gettext
|
||||||
import six
|
import six
|
||||||
|
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
gettext.install('octavia', unicode=1)
|
gettext.install('octavia', # pylint: disable=unexpected-keyword-arg
|
||||||
|
unicode=1)
|
||||||
else:
|
else:
|
||||||
gettext.install('octavia')
|
gettext.install('octavia')
|
||||||
|
|
|
@ -18,11 +18,11 @@ import re
|
||||||
import socket
|
import socket
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import netifaces
|
|
||||||
import pyroute2
|
import pyroute2
|
||||||
import six
|
import six
|
||||||
import webob
|
import webob
|
||||||
|
|
||||||
|
import netifaces
|
||||||
from octavia.amphorae.backends.agent import api_server
|
from octavia.amphorae.backends.agent import api_server
|
||||||
from octavia.amphorae.backends.agent.api_server import util
|
from octavia.amphorae.backends.agent.api_server import util
|
||||||
from octavia.common import constants as consts
|
from octavia.common import constants as consts
|
||||||
|
|
|
@ -480,8 +480,7 @@ class Listener(object):
|
||||||
m = re.search('frontend {}'.format(listener_id), cfg)
|
m = re.search('frontend {}'.format(listener_id), cfg)
|
||||||
if m:
|
if m:
|
||||||
return consts.ACTIVE
|
return consts.ACTIVE
|
||||||
else:
|
return consts.OFFLINE
|
||||||
return consts.OFFLINE
|
|
||||||
else: # pid file but no process...
|
else: # pid file but no process...
|
||||||
return consts.ERROR
|
return consts.ERROR
|
||||||
else:
|
else:
|
||||||
|
@ -539,8 +538,8 @@ class Listener(object):
|
||||||
if action == consts.AMP_ACTION_STOP:
|
if action == consts.AMP_ACTION_STOP:
|
||||||
listener_ids.remove(listener_id)
|
listener_ids.remove(listener_id)
|
||||||
args = []
|
args = []
|
||||||
for listener_id in listener_ids:
|
for lid in listener_ids:
|
||||||
args.append(util.haproxy_sock_path(listener_id))
|
args.append(util.haproxy_sock_path(lid))
|
||||||
|
|
||||||
if not os.path.exists(util.keepalived_dir()):
|
if not os.path.exists(util.keepalived_dir()):
|
||||||
os.makedirs(util.keepalived_dir())
|
os.makedirs(util.keepalived_dir())
|
||||||
|
@ -555,7 +554,4 @@ class Listener(object):
|
||||||
if os.path.exists(
|
if os.path.exists(
|
||||||
os.path.join('/proc', util.get_haproxy_pid(listener_id))):
|
os.path.join('/proc', util.get_haproxy_pid(listener_id))):
|
||||||
return consts.ACTIVE
|
return consts.ACTIVE
|
||||||
else: # pid file but no process...
|
return consts.OFFLINE
|
||||||
return consts.OFFLINE
|
|
||||||
else:
|
|
||||||
return consts.OFFLINE
|
|
||||||
|
|
|
@ -95,14 +95,14 @@ class BaseOS(object):
|
||||||
text = template_vip.render(
|
text = template_vip.render(
|
||||||
interface=primary_interface,
|
interface=primary_interface,
|
||||||
vip=vip,
|
vip=vip,
|
||||||
vip_ipv6=ip.version is 6,
|
vip_ipv6=ip.version == 6,
|
||||||
prefix=utils.netmask_to_prefix(netmask),
|
prefix=utils.netmask_to_prefix(netmask),
|
||||||
broadcast=broadcast,
|
broadcast=broadcast,
|
||||||
netmask=netmask,
|
netmask=netmask,
|
||||||
gateway=gateway,
|
gateway=gateway,
|
||||||
mtu=mtu,
|
mtu=mtu,
|
||||||
vrrp_ip=vrrp_ip,
|
vrrp_ip=vrrp_ip,
|
||||||
vrrp_ipv6=vrrp_version is 6,
|
vrrp_ipv6=vrrp_version == 6,
|
||||||
host_routes=render_host_routes,
|
host_routes=render_host_routes,
|
||||||
)
|
)
|
||||||
text_file.write(text)
|
text_file.write(text)
|
||||||
|
@ -149,7 +149,7 @@ class BaseOS(object):
|
||||||
cidr if isinstance(
|
cidr if isinstance(
|
||||||
cidr, six.text_type) else six.u(cidr))
|
cidr, six.text_type) else six.u(cidr))
|
||||||
broadcast = network.broadcast_address.exploded
|
broadcast = network.broadcast_address.exploded
|
||||||
netmask = (network.prefixlen if ip.version is 6
|
netmask = (network.prefixlen if ip.version == 6
|
||||||
else network.netmask.exploded)
|
else network.netmask.exploded)
|
||||||
host_routes = self.get_host_routes(fixed_ip)
|
host_routes = self.get_host_routes(fixed_ip)
|
||||||
|
|
||||||
|
@ -157,7 +157,7 @@ class BaseOS(object):
|
||||||
return webob.Response(
|
return webob.Response(
|
||||||
json=dict(message="Invalid network IP"), status=400)
|
json=dict(message="Invalid network IP"), status=400)
|
||||||
new_text = template_port.render(interface=netns_ip_interface,
|
new_text = template_port.render(interface=netns_ip_interface,
|
||||||
ipv6=ip.version is 6,
|
ipv6=ip.version == 6,
|
||||||
ip_address=ip.exploded,
|
ip_address=ip.exploded,
|
||||||
broadcast=broadcast,
|
broadcast=broadcast,
|
||||||
netmask=netmask,
|
netmask=netmask,
|
||||||
|
|
|
@ -20,7 +20,6 @@ import stat
|
||||||
import subprocess
|
import subprocess
|
||||||
|
|
||||||
import jinja2
|
import jinja2
|
||||||
import netifaces
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
import pyroute2
|
import pyroute2
|
||||||
|
@ -28,6 +27,7 @@ import six
|
||||||
import webob
|
import webob
|
||||||
from werkzeug import exceptions
|
from werkzeug import exceptions
|
||||||
|
|
||||||
|
import netifaces
|
||||||
from octavia.common import constants as consts
|
from octavia.common import constants as consts
|
||||||
|
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ class Plug(object):
|
||||||
else six.u(subnet_cidr))
|
else six.u(subnet_cidr))
|
||||||
vip = ip.exploded
|
vip = ip.exploded
|
||||||
broadcast = network.broadcast_address.exploded
|
broadcast = network.broadcast_address.exploded
|
||||||
netmask = (network.prefixlen if ip.version is 6
|
netmask = (network.prefixlen if ip.version == 6
|
||||||
else network.netmask.exploded)
|
else network.netmask.exploded)
|
||||||
vrrp_version = None
|
vrrp_version = None
|
||||||
if vrrp_ip:
|
if vrrp_ip:
|
||||||
|
|
|
@ -136,8 +136,7 @@ def get_os_init_system():
|
||||||
if os.path.exists(init_path):
|
if os.path.exists(init_path):
|
||||||
args = [init_path, '--version']
|
args = [init_path, '--version']
|
||||||
init_version = subprocess.check_output(args, shell=False)
|
init_version = subprocess.check_output(args, shell=False)
|
||||||
if consts.INIT_UPSTART in init_version:
|
if consts.INIT_UPSTART in str(init_version, 'utf-8'):
|
||||||
return consts.INIT_UPSTART
|
return consts.INIT_UPSTART
|
||||||
else:
|
return consts.INIT_SYSVINIT
|
||||||
return consts.INIT_SYSVINIT
|
|
||||||
return consts.INIT_UNKOWN
|
return consts.INIT_UNKOWN
|
||||||
|
|
|
@ -27,9 +27,10 @@ from octavia.amphorae.backends.health_daemon import health_sender
|
||||||
from octavia.amphorae.backends.utils import haproxy_query
|
from octavia.amphorae.backends.utils import haproxy_query
|
||||||
|
|
||||||
if six.PY2:
|
if six.PY2:
|
||||||
import Queue as queue
|
import Queue as queue # pylint: disable=wrong-import-order
|
||||||
else:
|
else:
|
||||||
import queue
|
import queue # pylint: disable=wrong-import-order
|
||||||
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
@ -91,10 +92,10 @@ def run_sender(cmd_queue):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
cmd = cmd_queue.get_nowait()
|
cmd = cmd_queue.get_nowait()
|
||||||
if cmd is 'reload':
|
if cmd == 'reload':
|
||||||
LOG.info('Reloading configuration')
|
LOG.info('Reloading configuration')
|
||||||
CONF.reload_config_files()
|
CONF.reload_config_files()
|
||||||
elif cmd is 'shutdown':
|
elif cmd == 'shutdown':
|
||||||
LOG.info('Health Manager Sender shutting down.')
|
LOG.info('Health Manager Sender shutting down.')
|
||||||
break
|
break
|
||||||
except queue.Empty:
|
except queue.Empty:
|
||||||
|
|
|
@ -44,7 +44,7 @@ class Details(models.BaseDataModel):
|
||||||
active=None, haproxy_count=None, cpu=None, memory=None,
|
active=None, haproxy_count=None, cpu=None, memory=None,
|
||||||
disk=None, load=None, listeners=None, packages=None):
|
disk=None, load=None, listeners=None, packages=None):
|
||||||
self.hostname = hostname
|
self.hostname = hostname
|
||||||
self.uuid = uuid,
|
self.uuid = uuid
|
||||||
self.version = version
|
self.version = version
|
||||||
self.api_version = api_version
|
self.api_version = api_version
|
||||||
self.network_tx = network_tx
|
self.network_tx = network_tx
|
||||||
|
|
|
@ -324,6 +324,7 @@ class AmphoraAPIClient(object):
|
||||||
'listeners/{listener_id}'.format(listener_id=listener_id))
|
'listeners/{listener_id}'.format(listener_id=listener_id))
|
||||||
if exc.check_exception(r):
|
if exc.check_exception(r):
|
||||||
return r.json()
|
return r.json()
|
||||||
|
return None
|
||||||
|
|
||||||
def _action(self, action, amp, listener_id):
|
def _action(self, action, amp, listener_id):
|
||||||
r = self.put(amp, 'listeners/{listener_id}/{action}'.format(
|
r = self.put(amp, 'listeners/{listener_id}/{action}'.format(
|
||||||
|
@ -348,6 +349,7 @@ class AmphoraAPIClient(object):
|
||||||
listener_id=listener_id, filename=pem_filename))
|
listener_id=listener_id, filename=pem_filename))
|
||||||
if exc.check_exception(r):
|
if exc.check_exception(r):
|
||||||
return r.json().get("md5sum")
|
return r.json().get("md5sum")
|
||||||
|
return None
|
||||||
|
|
||||||
def delete_listener(self, amp, listener_id):
|
def delete_listener(self, amp, listener_id):
|
||||||
r = self.delete(
|
r = self.delete(
|
||||||
|
@ -359,16 +361,19 @@ class AmphoraAPIClient(object):
|
||||||
r = self.get(amp, "info")
|
r = self.get(amp, "info")
|
||||||
if exc.check_exception(r):
|
if exc.check_exception(r):
|
||||||
return r.json()
|
return r.json()
|
||||||
|
return None
|
||||||
|
|
||||||
def get_details(self, amp):
|
def get_details(self, amp):
|
||||||
r = self.get(amp, "details")
|
r = self.get(amp, "details")
|
||||||
if exc.check_exception(r):
|
if exc.check_exception(r):
|
||||||
return r.json()
|
return r.json()
|
||||||
|
return None
|
||||||
|
|
||||||
def get_all_listeners(self, amp):
|
def get_all_listeners(self, amp):
|
||||||
r = self.get(amp, "listeners")
|
r = self.get(amp, "listeners")
|
||||||
if exc.check_exception(r):
|
if exc.check_exception(r):
|
||||||
return r.json()
|
return r.json()
|
||||||
|
return None
|
||||||
|
|
||||||
def delete_cert_pem(self, amp, listener_id, pem_filename):
|
def delete_cert_pem(self, amp, listener_id, pem_filename):
|
||||||
r = self.delete(
|
r = self.delete(
|
||||||
|
@ -400,3 +405,4 @@ class AmphoraAPIClient(object):
|
||||||
r = self.get(amp, 'interface/{ip_addr}'.format(ip_addr=ip_addr))
|
r = self.get(amp, 'interface/{ip_addr}'.format(ip_addr=ip_addr))
|
||||||
if exc.check_exception(r):
|
if exc.check_exception(r):
|
||||||
return r.json()
|
return r.json()
|
||||||
|
return None
|
||||||
|
|
|
@ -67,8 +67,8 @@ def simulate_controller(data_model, delete=False, update=False, create=False,
|
||||||
operating_status=constants.ONLINE)
|
operating_status=constants.ONLINE)
|
||||||
elif batch_update:
|
elif batch_update:
|
||||||
members = member
|
members = member
|
||||||
for member in members:
|
for m in members:
|
||||||
repo.member.update(db_api.get_session(), member.id,
|
repo.member.update(db_api.get_session(), m.id,
|
||||||
operating_status=constants.ONLINE)
|
operating_status=constants.ONLINE)
|
||||||
listeners = []
|
listeners = []
|
||||||
if db_mem:
|
if db_mem:
|
||||||
|
|
|
@ -169,7 +169,7 @@ class L7PolicyController(base.BaseController):
|
||||||
which controller, if any, should control be passed.
|
which controller, if any, should control be passed.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
if l7policy_id and len(remainder) and remainder[0] == 'l7rules':
|
if l7policy_id and remainder and remainder[0] == 'l7rules':
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
db_l7policy = self.repositories.l7policy.get(
|
db_l7policy = self.repositories.l7policy.get(
|
||||||
context.session, id=l7policy_id)
|
context.session, id=l7policy_id)
|
||||||
|
@ -181,3 +181,4 @@ class L7PolicyController(base.BaseController):
|
||||||
load_balancer_id=self.load_balancer_id,
|
load_balancer_id=self.load_balancer_id,
|
||||||
listener_id=self.listener_id,
|
listener_id=self.listener_id,
|
||||||
l7policy_id=db_l7policy.id), remainder
|
l7policy_id=db_l7policy.id), remainder
|
||||||
|
return None
|
||||||
|
|
|
@ -251,9 +251,14 @@ class ListenersController(base.BaseController):
|
||||||
which controller, if any, should control be passed.
|
which controller, if any, should control be passed.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
if listener_id and len(remainder) and (remainder[0] == 'pools' or
|
is_children = (
|
||||||
remainder[0] == 'l7policies' or
|
listener_id and remainder and (
|
||||||
remainder[0] == 'stats'):
|
remainder[0] == 'pools' or (
|
||||||
|
remainder[0] == 'l7policies' or remainder[0] == 'stats'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if is_children:
|
||||||
controller = remainder[0]
|
controller = remainder[0]
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
db_listener = self.repositories.listener.get(
|
db_listener = self.repositories.listener.get(
|
||||||
|
@ -273,3 +278,4 @@ class ListenersController(base.BaseController):
|
||||||
elif controller == 'stats':
|
elif controller == 'stats':
|
||||||
return listener_statistics.ListenerStatisticsController(
|
return listener_statistics.ListenerStatisticsController(
|
||||||
listener_id=db_listener.id), remainder
|
listener_id=db_listener.id), remainder
|
||||||
|
return None
|
||||||
|
|
|
@ -271,7 +271,7 @@ class LoadBalancersController(base.BaseController):
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
|
|
||||||
possible_remainder = ('listeners', 'pools', 'delete_cascade', 'stats')
|
possible_remainder = ('listeners', 'pools', 'delete_cascade', 'stats')
|
||||||
if lb_id and len(remainder) and (remainder[0] in possible_remainder):
|
if lb_id and remainder and (remainder[0] in possible_remainder):
|
||||||
controller = remainder[0]
|
controller = remainder[0]
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
db_lb = self.repositories.load_balancer.get(context.session,
|
db_lb = self.repositories.load_balancer.get(context.session,
|
||||||
|
@ -291,6 +291,7 @@ class LoadBalancersController(base.BaseController):
|
||||||
elif controller == 'stats':
|
elif controller == 'stats':
|
||||||
return lb_stats.LoadBalancerStatisticsController(
|
return lb_stats.LoadBalancerStatisticsController(
|
||||||
loadbalancer_id=db_lb.id), remainder
|
loadbalancer_id=db_lb.id), remainder
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class LBCascadeDeleteController(LoadBalancersController):
|
class LBCascadeDeleteController(LoadBalancersController):
|
||||||
|
|
|
@ -200,7 +200,7 @@ class PoolsController(base.BaseController):
|
||||||
"""Deletes a pool from a load balancer."""
|
"""Deletes a pool from a load balancer."""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
db_pool = self._get_db_pool(context.session, id)
|
db_pool = self._get_db_pool(context.session, id)
|
||||||
if len(db_pool.l7policies) > 0:
|
if db_pool.l7policies:
|
||||||
raise exceptions.PoolInUseByL7Policy(
|
raise exceptions.PoolInUseByL7Policy(
|
||||||
id=db_pool.id, l7policy_id=db_pool.l7policies[0].id)
|
id=db_pool.id, l7policy_id=db_pool.l7policies[0].id)
|
||||||
self._test_lb_and_listener_statuses(context.session, pool=db_pool)
|
self._test_lb_and_listener_statuses(context.session, pool=db_pool)
|
||||||
|
@ -228,8 +228,12 @@ class PoolsController(base.BaseController):
|
||||||
which controller, if any, should control be passed.
|
which controller, if any, should control be passed.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
if pool_id and len(remainder) and (remainder[0] == 'members' or
|
is_children = (
|
||||||
remainder[0] == 'healthmonitor'):
|
pool_id and remainder and (
|
||||||
|
remainder[0] == 'members' or remainder[0] == 'healthmonitor'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if is_children:
|
||||||
controller = remainder[0]
|
controller = remainder[0]
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
db_pool = self.repositories.pool.get(context.session, id=pool_id)
|
db_pool = self.repositories.pool.get(context.session, id=pool_id)
|
||||||
|
@ -247,3 +251,4 @@ class PoolsController(base.BaseController):
|
||||||
load_balancer_id=self.load_balancer_id,
|
load_balancer_id=self.load_balancer_id,
|
||||||
pool_id=db_pool.id,
|
pool_id=db_pool.id,
|
||||||
listener_id=self.listener_id), remainder
|
listener_id=self.listener_id), remainder
|
||||||
|
return None
|
||||||
|
|
|
@ -81,8 +81,9 @@ class QuotasController(base.BaseController):
|
||||||
@pecan.expose()
|
@pecan.expose()
|
||||||
def _lookup(self, project_id, *remainder):
|
def _lookup(self, project_id, *remainder):
|
||||||
"""Overridden pecan _lookup method for routing default endpoint."""
|
"""Overridden pecan _lookup method for routing default endpoint."""
|
||||||
if project_id and len(remainder) and remainder[0] == 'default':
|
if project_id and remainder and remainder[0] == 'default':
|
||||||
return QuotasDefaultController(project_id), ''
|
return QuotasDefaultController(project_id), ''
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class QuotasDefaultController(base.BaseController):
|
class QuotasDefaultController(base.BaseController):
|
||||||
|
|
|
@ -79,11 +79,12 @@ class AmphoraController(base.BaseController):
|
||||||
Currently it checks if this was a failover request and routes
|
Currently it checks if this was a failover request and routes
|
||||||
the request to the FailoverController.
|
the request to the FailoverController.
|
||||||
"""
|
"""
|
||||||
if amphora_id and len(remainder):
|
if amphora_id and remainder:
|
||||||
controller = remainder[0]
|
controller = remainder[0]
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
if controller == 'failover':
|
if controller == 'failover':
|
||||||
return FailoverController(amp_id=amphora_id), remainder
|
return FailoverController(amp_id=amphora_id), remainder
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class FailoverController(base.BaseController):
|
class FailoverController(base.BaseController):
|
||||||
|
|
|
@ -298,7 +298,7 @@ class L7PolicyController(base.BaseController):
|
||||||
which controller, if any, should control be passed.
|
which controller, if any, should control be passed.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
if l7policy_id and len(remainder) and remainder[0] == 'rules':
|
if l7policy_id and remainder and remainder[0] == 'rules':
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
db_l7policy = self.repositories.l7policy.get(
|
db_l7policy = self.repositories.l7policy.get(
|
||||||
context.session, id=l7policy_id)
|
context.session, id=l7policy_id)
|
||||||
|
@ -308,3 +308,4 @@ class L7PolicyController(base.BaseController):
|
||||||
resource='L7Policy', id=l7policy_id)
|
resource='L7Policy', id=l7policy_id)
|
||||||
return l7rule.L7RuleController(
|
return l7rule.L7RuleController(
|
||||||
l7policy_id=db_l7policy.id), remainder
|
l7policy_id=db_l7policy.id), remainder
|
||||||
|
return None
|
||||||
|
|
|
@ -377,8 +377,9 @@ class ListenersController(base.BaseController):
|
||||||
Currently it checks if this was a stats request and routes
|
Currently it checks if this was a stats request and routes
|
||||||
the request to the StatsController.
|
the request to the StatsController.
|
||||||
"""
|
"""
|
||||||
if id and len(remainder) and remainder[0] == 'stats':
|
if id and remainder and remainder[0] == 'stats':
|
||||||
return StatisticsController(listener_id=id), remainder[1:]
|
return StatisticsController(listener_id=id), remainder[1:]
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class StatisticsController(base.BaseController, stats.StatsMixin):
|
class StatisticsController(base.BaseController, stats.StatsMixin):
|
||||||
|
|
|
@ -535,10 +535,14 @@ class LoadBalancersController(base.BaseController):
|
||||||
'statuses' is aliased here for backward compatibility with
|
'statuses' is aliased here for backward compatibility with
|
||||||
neutron-lbaas LBaaS v2 API.
|
neutron-lbaas LBaaS v2 API.
|
||||||
"""
|
"""
|
||||||
if id and len(remainder) and (remainder[0] == 'status' or
|
is_children = (
|
||||||
remainder[0] == 'statuses' or
|
id and remainder and (
|
||||||
remainder[0] == 'stats' or
|
remainder[0] == 'status' or remainder[0] == 'statuses' or (
|
||||||
remainder[0] == 'failover'):
|
remainder[0] == 'stats' or remainder[0] == 'failover'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
if is_children:
|
||||||
controller = remainder[0]
|
controller = remainder[0]
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
if controller == 'status' or controller == 'statuses':
|
if controller == 'status' or controller == 'statuses':
|
||||||
|
@ -547,6 +551,7 @@ class LoadBalancersController(base.BaseController):
|
||||||
return StatisticsController(lb_id=id), remainder
|
return StatisticsController(lb_id=id), remainder
|
||||||
elif controller == 'failover':
|
elif controller == 'failover':
|
||||||
return FailoverController(lb_id=id), remainder
|
return FailoverController(lb_id=id), remainder
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class StatusController(base.BaseController):
|
class StatusController(base.BaseController):
|
||||||
|
|
|
@ -306,7 +306,7 @@ class PoolsController(base.BaseController):
|
||||||
"""Deletes a pool from a load balancer."""
|
"""Deletes a pool from a load balancer."""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
db_pool = self._get_db_pool(context.session, id, show_deleted=False)
|
db_pool = self._get_db_pool(context.session, id, show_deleted=False)
|
||||||
if len(db_pool.l7policies) > 0:
|
if db_pool.l7policies:
|
||||||
raise exceptions.PoolInUseByL7Policy(
|
raise exceptions.PoolInUseByL7Policy(
|
||||||
id=db_pool.id, l7policy_id=db_pool.l7policies[0].id)
|
id=db_pool.id, l7policy_id=db_pool.l7policies[0].id)
|
||||||
|
|
||||||
|
@ -337,7 +337,7 @@ class PoolsController(base.BaseController):
|
||||||
which controller, if any, should control be passed.
|
which controller, if any, should control be passed.
|
||||||
"""
|
"""
|
||||||
context = pecan.request.context.get('octavia_context')
|
context = pecan.request.context.get('octavia_context')
|
||||||
if pool_id and len(remainder) and remainder[0] == 'members':
|
if pool_id and remainder and remainder[0] == 'members':
|
||||||
remainder = remainder[1:]
|
remainder = remainder[1:]
|
||||||
db_pool = self.repositories.pool.get(context.session, id=pool_id)
|
db_pool = self.repositories.pool.get(context.session, id=pool_id)
|
||||||
if not db_pool:
|
if not db_pool:
|
||||||
|
@ -346,5 +346,5 @@ class PoolsController(base.BaseController):
|
||||||
id=pool_id)
|
id=pool_id)
|
||||||
if remainder:
|
if remainder:
|
||||||
return member.MemberController(pool_id=db_pool.id), remainder
|
return member.MemberController(pool_id=db_pool.id), remainder
|
||||||
else:
|
return member.MembersController(pool_id=db_pool.id), remainder
|
||||||
return member.MembersController(pool_id=db_pool.id), remainder
|
return None
|
||||||
|
|
|
@ -93,8 +93,9 @@ class QuotasController(base.BaseController):
|
||||||
@pecan.expose()
|
@pecan.expose()
|
||||||
def _lookup(self, project_id, *remainder):
|
def _lookup(self, project_id, *remainder):
|
||||||
"""Overridden pecan _lookup method for routing default endpoint."""
|
"""Overridden pecan _lookup method for routing default endpoint."""
|
||||||
if project_id and len(remainder) and remainder[0] == 'default':
|
if project_id and remainder and remainder[0] == 'default':
|
||||||
return QuotasDefaultController(project_id), ''
|
return QuotasDefaultController(project_id), ''
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class QuotasDefaultController(base.BaseController):
|
class QuotasDefaultController(base.BaseController):
|
||||||
|
|
|
@ -40,6 +40,7 @@ class BarbicanCert(cert.Cert):
|
||||||
if self._cert_container.certificate:
|
if self._cert_container.certificate:
|
||||||
return encodeutils.to_utf8(
|
return encodeutils.to_utf8(
|
||||||
self._cert_container.certificate.payload)
|
self._cert_container.certificate.payload)
|
||||||
|
return None
|
||||||
|
|
||||||
def get_intermediates(self):
|
def get_intermediates(self):
|
||||||
if self._cert_container.intermediates:
|
if self._cert_container.intermediates:
|
||||||
|
@ -47,16 +48,19 @@ class BarbicanCert(cert.Cert):
|
||||||
self._cert_container.intermediates.payload)
|
self._cert_container.intermediates.payload)
|
||||||
return [imd for imd in cert_parser.get_intermediates_pems(
|
return [imd for imd in cert_parser.get_intermediates_pems(
|
||||||
intermediates)]
|
intermediates)]
|
||||||
|
return None
|
||||||
|
|
||||||
def get_private_key(self):
|
def get_private_key(self):
|
||||||
if self._cert_container.private_key:
|
if self._cert_container.private_key:
|
||||||
return encodeutils.to_utf8(
|
return encodeutils.to_utf8(
|
||||||
self._cert_container.private_key.payload)
|
self._cert_container.private_key.payload)
|
||||||
|
return None
|
||||||
|
|
||||||
def get_private_key_passphrase(self):
|
def get_private_key_passphrase(self):
|
||||||
if self._cert_container.private_key_passphrase:
|
if self._cert_container.private_key_passphrase:
|
||||||
return encodeutils.to_utf8(
|
return encodeutils.to_utf8(
|
||||||
self._cert_container.private_key_passphrase.payload)
|
self._cert_container.private_key_passphrase.payload)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
@six.add_metaclass(abc.ABCMeta)
|
@six.add_metaclass(abc.ABCMeta)
|
||||||
|
|
|
@ -43,6 +43,7 @@ class PKCS12Cert(cert.Cert):
|
||||||
for ic in self.intermediates
|
for ic in self.intermediates
|
||||||
]
|
]
|
||||||
return int_data
|
return int_data
|
||||||
|
return None
|
||||||
|
|
||||||
def get_private_key(self):
|
def get_private_key(self):
|
||||||
return self.private_key.to_cryptography_key().private_bytes(
|
return self.private_key.to_cryptography_key().private_bytes(
|
||||||
|
|
|
@ -38,7 +38,7 @@ def get_status(sock_address):
|
||||||
data += x
|
data += x
|
||||||
s.close()
|
s.close()
|
||||||
# if get nothing, means has no response
|
# if get nothing, means has no response
|
||||||
if len(data) == 0:
|
if not data:
|
||||||
return 1
|
return 1
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
|
@ -389,7 +389,7 @@ class Listener(BaseDataModel):
|
||||||
if self.default_pool is not None:
|
if self.default_pool is not None:
|
||||||
l7_pool_ids = [p.redirect_pool_id for p in self.l7policies
|
l7_pool_ids = [p.redirect_pool_id for p in self.l7policies
|
||||||
if p.redirect_pool_id is not None and
|
if p.redirect_pool_id is not None and
|
||||||
len(p.l7rules) > 0 and p.enabled is True]
|
p.l7rules and p.enabled is True]
|
||||||
old_pool = self.default_pool
|
old_pool = self.default_pool
|
||||||
if old_pool.id not in l7_pool_ids:
|
if old_pool.id not in l7_pool_ids:
|
||||||
if old_pool in self.pools:
|
if old_pool in self.pools:
|
||||||
|
@ -620,7 +620,7 @@ class L7Policy(BaseDataModel):
|
||||||
listener_l7pools = [
|
listener_l7pools = [
|
||||||
p.redirect_pool for p in self.listener.l7policies
|
p.redirect_pool for p in self.listener.l7policies
|
||||||
if p.redirect_pool is not None and
|
if p.redirect_pool is not None and
|
||||||
len(p.l7rules) > 0 and p.enabled is True and
|
p.l7rules and p.enabled is True and
|
||||||
p.id != self.id]
|
p.id != self.id]
|
||||||
if pool not in listener_l7pools:
|
if pool not in listener_l7pools:
|
||||||
self.listener.pools.remove(pool)
|
self.listener.pools.remove(pool)
|
||||||
|
@ -634,7 +634,7 @@ class L7Policy(BaseDataModel):
|
||||||
self.redirect_url = None
|
self.redirect_url = None
|
||||||
pool = self._find_in_graph('Pool' + value)
|
pool = self._find_in_graph('Pool' + value)
|
||||||
self.redirect_pool = pool
|
self.redirect_pool = pool
|
||||||
if len(self.l7rules) > 0 and (self.enabled is True or (
|
if self.l7rules and (self.enabled is True or (
|
||||||
'enabled' in update_dict.keys() and
|
'enabled' in update_dict.keys() and
|
||||||
update_dict['enabled'] is True)):
|
update_dict['enabled'] is True)):
|
||||||
if pool not in self.listener.pools:
|
if pool not in self.listener.pools:
|
||||||
|
@ -658,7 +658,7 @@ class L7Policy(BaseDataModel):
|
||||||
if (value is True and self.action ==
|
if (value is True and self.action ==
|
||||||
constants.L7POLICY_ACTION_REDIRECT_TO_POOL and
|
constants.L7POLICY_ACTION_REDIRECT_TO_POOL and
|
||||||
self.redirect_pool is not None and
|
self.redirect_pool is not None and
|
||||||
len(self.l7rules) > 0 and
|
self.l7rules and
|
||||||
self.redirect_pool not in self.listener.pools):
|
self.redirect_pool not in self.listener.pools):
|
||||||
self.listener.pools.append(self.redirect_pool)
|
self.listener.pools.append(self.redirect_pool)
|
||||||
self.redirect_pool.listeners.append(self.listener)
|
self.redirect_pool.listeners.append(self.listener)
|
||||||
|
|
|
@ -38,7 +38,7 @@ class OctaviaException(Exception):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
try:
|
try:
|
||||||
if len(args) > 0:
|
if args:
|
||||||
self.message = args[0]
|
self.message = args[0]
|
||||||
self.orig_msg = kwargs.get('orig_msg')
|
self.orig_msg = kwargs.get('orig_msg')
|
||||||
self.orig_code = kwargs.get('orig_code')
|
self.orig_code = kwargs.get('orig_code')
|
||||||
|
|
|
@ -14,10 +14,11 @@
|
||||||
|
|
||||||
from keystoneauth1 import loading as ks_loading
|
from keystoneauth1 import loading as ks_loading
|
||||||
from keystonemiddleware import auth_token
|
from keystonemiddleware import auth_token
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
_NOAUTH_PATHS = ['/', '/load-balancer/']
|
_NOAUTH_PATHS = ['/', '/load-balancer/']
|
||||||
|
|
|
@ -70,8 +70,7 @@ def ip_port_str(ip_address, port):
|
||||||
ip = netaddr.IPAddress(ip_address)
|
ip = netaddr.IPAddress(ip_address)
|
||||||
if ip.version == 4:
|
if ip.version == 4:
|
||||||
return "{ip}:{port}".format(ip=ip, port=port)
|
return "{ip}:{port}".format(ip=ip, port=port)
|
||||||
elif ip.version == 6:
|
return "[{ip}]:{port}".format(ip=ip, port=port)
|
||||||
return "[{ip}]:{port}".format(ip=ip, port=port)
|
|
||||||
|
|
||||||
|
|
||||||
def netmask_to_prefix(netmask):
|
def netmask_to_prefix(netmask):
|
||||||
|
|
|
@ -52,12 +52,14 @@ def url_path(url_path):
|
||||||
try:
|
try:
|
||||||
p_url = rfc3986.urlparse(rfc3986.normalize_uri(url_path))
|
p_url = rfc3986.urlparse(rfc3986.normalize_uri(url_path))
|
||||||
|
|
||||||
if (
|
invalid_path = (
|
||||||
p_url.scheme or p_url.userinfo or p_url.host or
|
p_url.scheme or p_url.userinfo or p_url.host or
|
||||||
p_url.port or
|
p_url.port or
|
||||||
p_url.path is None or
|
p_url.path is None or
|
||||||
not p_url.path.startswith('/')
|
not p_url.path.startswith('/')
|
||||||
):
|
)
|
||||||
|
|
||||||
|
if invalid_path:
|
||||||
raise exceptions.InvalidURLPath(url_path=url_path)
|
raise exceptions.InvalidURLPath(url_path=url_path)
|
||||||
except Exception:
|
except Exception:
|
||||||
raise exceptions.InvalidURLPath(url_path=url_path)
|
raise exceptions.InvalidURLPath(url_path=url_path)
|
||||||
|
@ -220,7 +222,7 @@ def sanitize_l7policy_api_args(l7policy, create=False):
|
||||||
raise exceptions.InvalidL7PolicyAction(action='None')
|
raise exceptions.InvalidL7PolicyAction(action='None')
|
||||||
|
|
||||||
# See if we have anything left after that...
|
# See if we have anything left after that...
|
||||||
if len(l7policy.keys()) == 0:
|
if not l7policy.keys():
|
||||||
raise exceptions.InvalidL7PolicyArgs(msg='Invalid update options')
|
raise exceptions.InvalidL7PolicyArgs(msg='Invalid update options')
|
||||||
return l7policy
|
return l7policy
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ LOG = logging.getLogger(__name__)
|
||||||
def wait_done_or_dead(futs, dead, check_timeout=1):
|
def wait_done_or_dead(futs, dead, check_timeout=1):
|
||||||
while True:
|
while True:
|
||||||
_done, not_done = futures.wait(futs, timeout=check_timeout)
|
_done, not_done = futures.wait(futs, timeout=check_timeout)
|
||||||
if len(not_done) == 0:
|
if not not_done:
|
||||||
break
|
break
|
||||||
if dead.is_set():
|
if dead.is_set():
|
||||||
for fut in not_done:
|
for fut in not_done:
|
||||||
|
@ -68,13 +68,12 @@ class HealthManager(object):
|
||||||
if self.lb_repo.set_status_for_failover(lock_session, lb_id,
|
if self.lb_repo.set_status_for_failover(lock_session, lb_id,
|
||||||
constants.PENDING_UPDATE):
|
constants.PENDING_UPDATE):
|
||||||
return True
|
return True
|
||||||
else:
|
db_lb = self.lb_repo.get(lock_session, id=lb_id)
|
||||||
db_lb = self.lb_repo.get(lock_session, id=lb_id)
|
prov_status = db_lb.provisioning_status
|
||||||
prov_status = db_lb.provisioning_status
|
LOG.warning("Load balancer %(id)s is in immutable state "
|
||||||
LOG.warning("Load balancer %(id)s is in immutable state "
|
"%(state)s. Skipping failover.",
|
||||||
"%(state)s. Skipping failover.",
|
{"state": prov_status, "id": db_lb.id})
|
||||||
{"state": prov_status, "id": db_lb.id})
|
return False
|
||||||
return False
|
|
||||||
|
|
||||||
def health_check(self):
|
def health_check(self):
|
||||||
stats = {
|
stats = {
|
||||||
|
|
|
@ -144,7 +144,7 @@ class PlugNetworks(BaseNetworkTask):
|
||||||
|
|
||||||
if not delta:
|
if not delta:
|
||||||
LOG.debug("No network deltas for amphora id: %s", amphora.id)
|
LOG.debug("No network deltas for amphora id: %s", amphora.id)
|
||||||
return None
|
return
|
||||||
|
|
||||||
# add nics
|
# add nics
|
||||||
for nic in delta.add_nics:
|
for nic in delta.add_nics:
|
||||||
|
@ -179,7 +179,7 @@ class UnPlugNetworks(BaseNetworkTask):
|
||||||
LOG.debug("Unplug network for amphora")
|
LOG.debug("Unplug network for amphora")
|
||||||
if not delta:
|
if not delta:
|
||||||
LOG.debug("No network deltas for amphora id: %s", amphora.id)
|
LOG.debug("No network deltas for amphora id: %s", amphora.id)
|
||||||
return None
|
return
|
||||||
|
|
||||||
for nic in delta.delete_nics:
|
for nic in delta.delete_nics:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -114,7 +114,7 @@ class BaseRepository(object):
|
||||||
model = model.first()
|
model = model.first()
|
||||||
|
|
||||||
if not model:
|
if not model:
|
||||||
return
|
return None
|
||||||
|
|
||||||
return model.to_data_model()
|
return model.to_data_model()
|
||||||
|
|
||||||
|
@ -246,7 +246,7 @@ class Repositories(object):
|
||||||
self.session_persistence.create(session, **sp_dict)
|
self.session_persistence.create(session, **sp_dict)
|
||||||
# If only the session_persistence is being updated, this will be
|
# If only the session_persistence is being updated, this will be
|
||||||
# empty
|
# empty
|
||||||
if len(pool_dict.keys()) > 0:
|
if pool_dict:
|
||||||
self.pool.update(session, pool_id, **pool_dict)
|
self.pool.update(session, pool_id, **pool_dict)
|
||||||
return self.pool.get(session, id=pool_id)
|
return self.pool.get(session, id=pool_id)
|
||||||
|
|
||||||
|
@ -355,8 +355,7 @@ class Repositories(object):
|
||||||
if lb_count <= lb_quota or lb_quota == consts.QUOTA_UNLIMITED:
|
if lb_count <= lb_quota or lb_quota == consts.QUOTA_UNLIMITED:
|
||||||
quotas.in_use_load_balancer = lb_count
|
quotas.in_use_load_balancer = lb_count
|
||||||
return False
|
return False
|
||||||
else:
|
return True
|
||||||
return True
|
|
||||||
elif _class == data_models.Listener:
|
elif _class == data_models.Listener:
|
||||||
# Decide which quota to use
|
# Decide which quota to use
|
||||||
if quotas.listener is None:
|
if quotas.listener is None:
|
||||||
|
@ -377,8 +376,7 @@ class Repositories(object):
|
||||||
listener_quota == consts.QUOTA_UNLIMITED):
|
listener_quota == consts.QUOTA_UNLIMITED):
|
||||||
quotas.in_use_listener = listener_count
|
quotas.in_use_listener = listener_count
|
||||||
return False
|
return False
|
||||||
else:
|
return True
|
||||||
return True
|
|
||||||
elif _class == data_models.Pool:
|
elif _class == data_models.Pool:
|
||||||
# Decide which quota to use
|
# Decide which quota to use
|
||||||
if quotas.pool is None:
|
if quotas.pool is None:
|
||||||
|
@ -399,8 +397,7 @@ class Repositories(object):
|
||||||
pool_quota == consts.QUOTA_UNLIMITED):
|
pool_quota == consts.QUOTA_UNLIMITED):
|
||||||
quotas.in_use_pool = pool_count
|
quotas.in_use_pool = pool_count
|
||||||
return False
|
return False
|
||||||
else:
|
return True
|
||||||
return True
|
|
||||||
elif _class == data_models.HealthMonitor:
|
elif _class == data_models.HealthMonitor:
|
||||||
# Decide which quota to use
|
# Decide which quota to use
|
||||||
if quotas.health_monitor is None:
|
if quotas.health_monitor is None:
|
||||||
|
@ -421,8 +418,7 @@ class Repositories(object):
|
||||||
hm_quota == consts.QUOTA_UNLIMITED):
|
hm_quota == consts.QUOTA_UNLIMITED):
|
||||||
quotas.in_use_health_monitor = hm_count
|
quotas.in_use_health_monitor = hm_count
|
||||||
return False
|
return False
|
||||||
else:
|
return True
|
||||||
return True
|
|
||||||
elif _class == data_models.Member:
|
elif _class == data_models.Member:
|
||||||
# Decide which quota to use
|
# Decide which quota to use
|
||||||
if quotas.member is None:
|
if quotas.member is None:
|
||||||
|
@ -443,8 +439,7 @@ class Repositories(object):
|
||||||
member_quota == consts.QUOTA_UNLIMITED):
|
member_quota == consts.QUOTA_UNLIMITED):
|
||||||
quotas.in_use_member = member_count
|
quotas.in_use_member = member_count
|
||||||
return False
|
return False
|
||||||
else:
|
return True
|
||||||
return True
|
|
||||||
except db_exception.DBDeadlock:
|
except db_exception.DBDeadlock:
|
||||||
LOG.warning('Quota project lock timed out for project: %(proj)s',
|
LOG.warning('Quota project lock timed out for project: %(proj)s',
|
||||||
{'proj': project_id})
|
{'proj': project_id})
|
||||||
|
@ -742,9 +737,8 @@ class LoadBalancerRepository(BaseRepository):
|
||||||
# If a load balancer was never updated use its creation timestamp
|
# If a load balancer was never updated use its creation timestamp
|
||||||
last_update = lb.updated_at or lb.created_at
|
last_update = lb.updated_at or lb.created_at
|
||||||
return last_update < timestamp
|
return last_update < timestamp
|
||||||
else:
|
# Load balancer was just deleted.
|
||||||
# Load balancer was just deleted.
|
return True
|
||||||
return True
|
|
||||||
|
|
||||||
|
|
||||||
class VipRepository(BaseRepository):
|
class VipRepository(BaseRepository):
|
||||||
|
@ -814,8 +808,7 @@ class ListenerRepository(BaseRepository):
|
||||||
max_peer_port = listener.peer_port
|
max_peer_port = listener.peer_port
|
||||||
if max_peer_port == 0:
|
if max_peer_port == 0:
|
||||||
return consts.HAPROXY_BASE_PEER_PORT
|
return consts.HAPROXY_BASE_PEER_PORT
|
||||||
else:
|
return max_peer_port + 1
|
||||||
return max_peer_port + 1
|
|
||||||
|
|
||||||
def _pool_check(self, session, pool_id, listener_id=None,
|
def _pool_check(self, session, pool_id, listener_id=None,
|
||||||
lb_id=None):
|
lb_id=None):
|
||||||
|
@ -965,6 +958,7 @@ class AmphoraRepository(BaseRepository):
|
||||||
).first()
|
).first()
|
||||||
if db_lb:
|
if db_lb:
|
||||||
return db_lb.to_data_model()
|
return db_lb.to_data_model()
|
||||||
|
return None
|
||||||
|
|
||||||
def get_all_deleted_expiring_amphora(self, session, exp_age=None):
|
def get_all_deleted_expiring_amphora(self, session, exp_age=None):
|
||||||
|
|
||||||
|
|
|
@ -112,6 +112,7 @@ def no_author_tags(physical_line):
|
||||||
if pos < 0:
|
if pos < 0:
|
||||||
pos = physical_line.find('author')
|
pos = physical_line.find('author')
|
||||||
return pos, "O322: Don't use author tags"
|
return pos, "O322: Don't use author tags"
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def assert_equal_true_or_false(logical_line):
|
def assert_equal_true_or_false(logical_line):
|
||||||
|
|
|
@ -94,6 +94,7 @@ class Port(data_models.BaseDataModel):
|
||||||
for fixed_ip in self.fixed_ips:
|
for fixed_ip in self.fixed_ips:
|
||||||
if fixed_ip.ip_address == fixed_ip_address:
|
if fixed_ip.ip_address == fixed_ip_address:
|
||||||
return fixed_ip.subnet_id
|
return fixed_ip.subnet_id
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
class FixedIP(data_models.BaseDataModel):
|
class FixedIP(data_models.BaseDataModel):
|
||||||
|
|
|
@ -82,6 +82,7 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||||
is_correct_interface = False
|
is_correct_interface = False
|
||||||
if is_correct_interface:
|
if is_correct_interface:
|
||||||
return interface
|
return interface
|
||||||
|
return None
|
||||||
|
|
||||||
def _plug_amphora_vip(self, amphora, subnet):
|
def _plug_amphora_vip(self, amphora, subnet):
|
||||||
# We need a vip port owned by Octavia for Act/Stby and failover
|
# We need a vip port owned by Octavia for Act/Stby and failover
|
||||||
|
@ -124,11 +125,12 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||||
sec_grps = self.neutron_client.list_security_groups(name=sec_grp_name)
|
sec_grps = self.neutron_client.list_security_groups(name=sec_grp_name)
|
||||||
if sec_grps and sec_grps.get('security_groups'):
|
if sec_grps and sec_grps.get('security_groups'):
|
||||||
return sec_grps.get('security_groups')[0]
|
return sec_grps.get('security_groups')[0]
|
||||||
|
return None
|
||||||
|
|
||||||
def _get_ethertype_for_ip(self, ip):
|
def _get_ethertype_for_ip(self, ip):
|
||||||
address = ipaddress.ip_address(
|
address = ipaddress.ip_address(
|
||||||
ip if isinstance(ip, six.text_type) else six.u(ip))
|
ip if isinstance(ip, six.text_type) else six.u(ip))
|
||||||
return 'IPv6' if address.version is 6 else 'IPv4'
|
return 'IPv6' if address.version == 6 else 'IPv4'
|
||||||
|
|
||||||
def _update_security_group_rules(self, load_balancer, sec_grp_id):
|
def _update_security_group_rules(self, load_balancer, sec_grp_id):
|
||||||
rules = self.neutron_client.list_security_group_rules(
|
rules = self.neutron_client.list_security_group_rules(
|
||||||
|
@ -276,8 +278,8 @@ class AllowedAddressPairsDriver(neutron_base.BaseNeutronDriver):
|
||||||
LOG.warning('Failed to delete security group on first '
|
LOG.warning('Failed to delete security group on first '
|
||||||
'pass: %s', sec_grp_id)
|
'pass: %s', sec_grp_id)
|
||||||
extra_ports = self._get_ports_by_security_group(sec_grp_id)
|
extra_ports = self._get_ports_by_security_group(sec_grp_id)
|
||||||
for port in extra_ports:
|
for extra_port in extra_ports:
|
||||||
port_id = port.get('id')
|
port_id = extra_port.get('id')
|
||||||
try:
|
try:
|
||||||
LOG.warning('Deleting extra port %s on security '
|
LOG.warning('Deleting extra port %s on security '
|
||||||
'group %s...', port_id, sec_grp_id)
|
'group %s...', port_id, sec_grp_id)
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_AMPHORA,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_AMPHORA,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_HEALTHMONITOR,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_L7POLICY,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_L7POLICY,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_L7RULE,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_L7RULE,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_LISTENER,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_LISTENER,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_LOADBALANCER,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_LOADBALANCER,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_MEMBER,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_MEMBER,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_POOL,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_POOL,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_PROVIDER,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_PROVIDER,
|
||||||
|
|
|
@ -11,9 +11,10 @@
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from octavia.common import constants
|
|
||||||
from oslo_policy import policy
|
from oslo_policy import policy
|
||||||
|
|
||||||
|
from octavia.common import constants
|
||||||
|
|
||||||
rules = [
|
rules = [
|
||||||
policy.DocumentedRuleDefault(
|
policy.DocumentedRuleDefault(
|
||||||
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_QUOTA,
|
'{rbac_obj}{action}'.format(rbac_obj=constants.RBAC_QUOTA,
|
||||||
|
|
|
@ -39,10 +39,10 @@ taskflow>=2.16.0 # Apache-2.0
|
||||||
diskimage-builder!=1.6.0,!=1.7.0,!=1.7.1,>=1.1.2 # Apache-2.0
|
diskimage-builder!=1.6.0,!=1.7.0,!=1.7.1,>=1.1.2 # Apache-2.0
|
||||||
futures>=3.0.0;python_version=='2.7' or python_version=='2.6' # BSD
|
futures>=3.0.0;python_version=='2.7' or python_version=='2.6' # BSD
|
||||||
castellan>=0.16.0 # Apache-2.0
|
castellan>=0.16.0 # Apache-2.0
|
||||||
tenacity # Apache-2.0
|
tenacity>=4.9.0 # Apache-2.0
|
||||||
|
|
||||||
#for the amphora api
|
#for the amphora api
|
||||||
Flask!=0.11,<1.0,>=0.10 # BSD
|
Flask!=0.11,>=0.10 # BSD
|
||||||
netifaces>=0.10.4 # MIT
|
netifaces>=0.10.4 # MIT
|
||||||
ipaddress>=1.0.17;python_version<'3.3' # PSF
|
ipaddress>=1.0.17;python_version<'3.3' # PSF
|
||||||
cryptography>=2.1 # BSD/Apache-2.0
|
cryptography>=2.1 # BSD/Apache-2.0
|
||||||
|
|
|
@ -9,7 +9,7 @@ mock>=2.0.0 # BSD
|
||||||
python-subunit>=1.0.0 # Apache-2.0/BSD
|
python-subunit>=1.0.0 # Apache-2.0/BSD
|
||||||
oslotest>=3.2.0 # Apache-2.0
|
oslotest>=3.2.0 # Apache-2.0
|
||||||
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
oslo.serialization!=2.19.1,>=2.18.0 # Apache-2.0
|
||||||
pylint==1.4.5 # GPLv2
|
pylint==1.9.2 # GPLv2
|
||||||
testrepository>=0.0.18 # Apache-2.0/BSD
|
testrepository>=0.0.18 # Apache-2.0/BSD
|
||||||
testtools>=2.2.0 # MIT
|
testtools>=2.2.0 # MIT
|
||||||
testresources>=2.0.0 # Apache-2.0/BSD
|
testresources>=2.0.0 # Apache-2.0/BSD
|
||||||
|
|
|
@ -48,7 +48,7 @@ run_pylint () {
|
||||||
echo "Running pylint..."
|
echo "Running pylint..."
|
||||||
echo "You can speed this up by running it on 'HEAD~[0-9]' (e.g. HEAD~1, this change only)..."
|
echo "You can speed this up by running it on 'HEAD~[0-9]' (e.g. HEAD~1, this change only)..."
|
||||||
if [ -n "${files}" ]; then
|
if [ -n "${files}" ]; then
|
||||||
pylint --rcfile=.pylintrc --output-format=colorized ${files}
|
pylint --max-nested-blocks 7 --extension-pkg-whitelist netifaces --rcfile=.pylintrc --output-format=colorized ${files}
|
||||||
else
|
else
|
||||||
echo "No python changes in this commit, pylint check not required."
|
echo "No python changes in this commit, pylint check not required."
|
||||||
exit 0
|
exit 0
|
||||||
|
|
14
tox.ini
14
tox.ini
|
@ -17,6 +17,7 @@ commands =
|
||||||
stestr slowest
|
stestr slowest
|
||||||
|
|
||||||
[testenv:api-ref]
|
[testenv:api-ref]
|
||||||
|
basepython = python3
|
||||||
# This environment is called from CI scripts to test and publish
|
# This environment is called from CI scripts to test and publish
|
||||||
# the API Ref to developer.openstack.org.
|
# the API Ref to developer.openstack.org.
|
||||||
deps =
|
deps =
|
||||||
|
@ -29,6 +30,7 @@ commands =
|
||||||
sphinx-build -W -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
|
sphinx-build -W -b html -d api-ref/build/doctrees api-ref/source api-ref/build/html
|
||||||
|
|
||||||
[testenv:cover]
|
[testenv:cover]
|
||||||
|
basepython = python3
|
||||||
whitelist_externals = sh
|
whitelist_externals = sh
|
||||||
setenv =
|
setenv =
|
||||||
{[testenv]setenv}
|
{[testenv]setenv}
|
||||||
|
@ -52,6 +54,7 @@ basepython = python3.5
|
||||||
setenv = OS_TEST_PATH={toxinidir}/octavia/tests/functional
|
setenv = OS_TEST_PATH={toxinidir}/octavia/tests/functional
|
||||||
|
|
||||||
[testenv:debug]
|
[testenv:debug]
|
||||||
|
basepython = python3
|
||||||
commands = oslo_debug_helper {posargs}
|
commands = oslo_debug_helper {posargs}
|
||||||
|
|
||||||
[testenv:debug-py27]
|
[testenv:debug-py27]
|
||||||
|
@ -63,6 +66,7 @@ basepython = python3.5
|
||||||
commands = oslo_debug_helper {posargs}
|
commands = oslo_debug_helper {posargs}
|
||||||
|
|
||||||
[testenv:pep8]
|
[testenv:pep8]
|
||||||
|
basepython = python3
|
||||||
commands = flake8
|
commands = flake8
|
||||||
# RST linter
|
# RST linter
|
||||||
doc8 --ignore-path doc/source/contributor/modules specs \
|
doc8 --ignore-path doc/source/contributor/modules specs \
|
||||||
|
@ -80,6 +84,7 @@ whitelist_externals =
|
||||||
find
|
find
|
||||||
|
|
||||||
[testenv:docs]
|
[testenv:docs]
|
||||||
|
basepython = python3
|
||||||
deps =
|
deps =
|
||||||
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
|
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
|
||||||
-r{toxinidir}/requirements.txt
|
-r{toxinidir}/requirements.txt
|
||||||
|
@ -91,9 +96,11 @@ commands =
|
||||||
sphinx-build -W -b html api-ref/source api-ref/build/html
|
sphinx-build -W -b html api-ref/source api-ref/build/html
|
||||||
|
|
||||||
[testenv:venv]
|
[testenv:venv]
|
||||||
|
basepython = python3
|
||||||
commands = {posargs}
|
commands = {posargs}
|
||||||
|
|
||||||
[testenv:genconfig]
|
[testenv:genconfig]
|
||||||
|
basepython = python3
|
||||||
whitelist_externals = mkdir
|
whitelist_externals = mkdir
|
||||||
commands =
|
commands =
|
||||||
mkdir -p etc/octavia
|
mkdir -p etc/octavia
|
||||||
|
@ -105,6 +112,7 @@ commands =
|
||||||
--namespace keystonemiddleware.auth_token
|
--namespace keystonemiddleware.auth_token
|
||||||
|
|
||||||
[testenv:genpolicy]
|
[testenv:genpolicy]
|
||||||
|
basepython = python3
|
||||||
whitelist_externals = mkdir
|
whitelist_externals = mkdir
|
||||||
commands =
|
commands =
|
||||||
mkdir -p etc/octavia
|
mkdir -p etc/octavia
|
||||||
|
@ -113,6 +121,7 @@ commands =
|
||||||
--output-file etc/octavia/json.policy.sample
|
--output-file etc/octavia/json.policy.sample
|
||||||
|
|
||||||
[testenv:specs]
|
[testenv:specs]
|
||||||
|
basepython = python3
|
||||||
whitelist_externals =
|
whitelist_externals =
|
||||||
rm
|
rm
|
||||||
find
|
find
|
||||||
|
@ -122,6 +131,7 @@ commands =
|
||||||
|
|
||||||
|
|
||||||
[testenv:bandit]
|
[testenv:bandit]
|
||||||
|
basepython = python3
|
||||||
commands = bandit -r octavia -ll -ii -x octavia/tests {posargs}
|
commands = bandit -r octavia -ll -ii -x octavia/tests {posargs}
|
||||||
|
|
||||||
[flake8]
|
[flake8]
|
||||||
|
@ -145,6 +155,7 @@ local-check-factory = octavia.hacking.checks.factory
|
||||||
max-line-length = 79
|
max-line-length = 79
|
||||||
|
|
||||||
[testenv:releasenotes]
|
[testenv:releasenotes]
|
||||||
|
basepython = python3
|
||||||
deps =
|
deps =
|
||||||
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
|
-c{env:UPPER_CONSTRAINTS_FILE:https://git.openstack.org/cgit/openstack/requirements/plain/upper-constraints.txt}
|
||||||
-r{toxinidir}/requirements.txt
|
-r{toxinidir}/requirements.txt
|
||||||
|
@ -157,6 +168,7 @@ commands =
|
||||||
# If you are running the tests locally you should set the env variable
|
# If you are running the tests locally you should set the env variable
|
||||||
# TEMPEST_CONFIG_DIR=/opt/stack/tempest/etc
|
# TEMPEST_CONFIG_DIR=/opt/stack/tempest/etc
|
||||||
[testenv:apiv1]
|
[testenv:apiv1]
|
||||||
|
basepython = python3
|
||||||
passenv = TEMPEST_CONFIG_DIR
|
passenv = TEMPEST_CONFIG_DIR
|
||||||
setenv =
|
setenv =
|
||||||
OS_TEST_PATH={toxinidir}/octavia/tests/tempest/v1/api
|
OS_TEST_PATH={toxinidir}/octavia/tests/tempest/v1/api
|
||||||
|
@ -167,6 +179,7 @@ commands =
|
||||||
# If you are running the tests locally you should set the env variable
|
# If you are running the tests locally you should set the env variable
|
||||||
# TEMPEST_CONFIG_DIR=/opt/stack/tempest/etc
|
# TEMPEST_CONFIG_DIR=/opt/stack/tempest/etc
|
||||||
[testenv:scenario]
|
[testenv:scenario]
|
||||||
|
basepython = python3
|
||||||
passenv = TEMPEST_CONFIG_DIR
|
passenv = TEMPEST_CONFIG_DIR
|
||||||
setenv =
|
setenv =
|
||||||
OS_TEST_PATH={toxinidir}/octavia/tests/tempest/v1/scenario
|
OS_TEST_PATH={toxinidir}/octavia/tests/tempest/v1/scenario
|
||||||
|
@ -186,6 +199,7 @@ commands =
|
||||||
sh -c 'OS_TEST_PATH={toxinidir}/octavia/tests/functional stestr run {posargs}'
|
sh -c 'OS_TEST_PATH={toxinidir}/octavia/tests/functional stestr run {posargs}'
|
||||||
|
|
||||||
[testenv:requirements]
|
[testenv:requirements]
|
||||||
|
basepython = python3
|
||||||
deps =
|
deps =
|
||||||
-egit+https://git.openstack.org/openstack/requirements#egg=openstack-requirements
|
-egit+https://git.openstack.org/openstack/requirements#egg=openstack-requirements
|
||||||
whitelist_externals = sh
|
whitelist_externals = sh
|
||||||
|
|
Loading…
Reference in New Issue