Merge remote-tracking branch 'origin' into merge-branch

This commit merges the master neutron branch into the feature/lbaasv2
branch. This is needed to get the feature/lbaasv2 branch building again.

Change-Id: Iba59aa20adc6b369b4b9d250afee406159287ba1
This commit is contained in:
Kyle Mestery 2014-10-24 10:53:51 +00:00
commit d969131246
34 changed files with 1935 additions and 2215 deletions

124
.pylintrc
View File

@ -2,17 +2,97 @@
[MASTER] [MASTER]
# Add <file or directory> to the black list. It should be a base name, not a # Add <file or directory> to the black list. It should be a base name, not a
# path. You may set this option multiple times. # path. You may set this option multiple times.
ignore=test #
# Note the 'openstack' below is intended to match only
# neutron.openstack.common. If we ever have another 'openstack'
# dirname, then we'll need to expand the ignore features in pylint :/
ignore=.git,tests,openstack
[Messages Control] [MESSAGES CONTROL]
# NOTE(justinsb): We might want to have a 2nd strict pylintrc in future # NOTE(gus): This is a long list. A number of these are important and
# C0111: Don't require docstrings on every method # should be re-enabled once the offending code is fixed (or marked
# W0511: TODOs in code comments are fine. # with a local disable)
# W0142: *args and **kwargs are fine. disable=
# W0622: Redefining id is fine. # "F" Fatal errors that prevent further processing
disable=C0111,W0511,W0142,W0622 import-error,
# "I" Informational noise
locally-disabled,
# "E" Error for important programming issues (likely bugs)
access-member-before-definition,
assignment-from-no-return,
bad-except-order,
bad-super-call,
maybe-no-member,
no-member,
no-method-argument,
no-name-in-module,
no-self-argument,
not-callable,
no-value-for-parameter,
super-on-old-class,
too-few-format-args,
# "W" Warnings for stylistic problems or minor programming issues
abstract-method,
anomalous-backslash-in-string,
anomalous-unicode-escape-in-string,
arguments-differ,
attribute-defined-outside-init,
bad-builtin,
bad-indentation,
broad-except,
dangerous-default-value,
deprecated-lambda,
duplicate-key,
expression-not-assigned,
fixme,
global-statement,
global-variable-not-assigned,
logging-not-lazy,
lost-exception,
no-init,
non-parent-init-called,
pointless-string-statement,
protected-access,
redefined-builtin,
redefined-outer-name,
redefine-in-handler,
signature-differs,
star-args,
super-init-not-called,
undefined-loop-variable,
unnecessary-lambda,
unnecessary-pass,
unpacking-non-sequence,
unreachable,
unused-argument,
unused-import,
unused-variable,
useless-else-on-loop,
# "C" Coding convention violations
bad-continuation,
invalid-name,
missing-docstring,
old-style-class,
superfluous-parens,
# "R" Refactor recommendations
abstract-class-little-used,
abstract-class-not-used,
cyclic-import,
duplicate-code,
interface-not-implemented,
no-self-use,
too-few-public-methods,
too-many-ancestors,
too-many-arguments,
too-many-branches,
too-many-instance-attributes,
too-many-lines,
too-many-locals,
too-many-public-methods,
too-many-return-statements,
too-many-statements
[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
variable-rgx=[a-z_][a-z0-9_]{0,30}$ variable-rgx=[a-z_][a-z0-9_]{0,30}$
@ -21,7 +101,7 @@ argument-rgx=[a-z_][a-z0-9_]{1,30}$
# Method names should be at least 3 characters long # Method names should be at least 3 characters long
# and be lowecased with underscores # and be lowecased with underscores
method-rgx=([a-z_][a-z0-9_]{2,50}|setUp|tearDown)$ method-rgx=([a-z_][a-z0-9_]{2,}|setUp|tearDown)$
# Module names matching neutron-* are ok (files in bin/) # Module names matching neutron-* are ok (files in bin/)
module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$ module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$
@ -29,14 +109,26 @@ module-rgx=(([a-z_][a-z0-9_]*)|([A-Z][a-zA-Z0-9]+)|(neutron-[a-z0-9_-]+))$
# Don't require docstrings on tests. # Don't require docstrings on tests.
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$ no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
[Design] [FORMAT]
max-public-methods=100 # Maximum number of characters on a single line.
min-public-methods=0 max-line-length=79
max-args=6
[Variables]
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that # List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible. # you should avoid to define new builtins when possible.
# _ is used by our localization # _ is used by our localization
additional-builtins=_ additional-builtins=_
[CLASSES]
# List of interface methods to ignore, separated by a comma.
ignore-iface-methods=
[IMPORTS]
# Deprecated modules which should not be used, separated by a comma
deprecated-modules=
# should use openstack.common.jsonutils
json
[REPORTS]
# Tells whether to display a full report or only the messages
reports=no

View File

@ -12,6 +12,7 @@ Neutron Specific Commandments
- [N321] Validate that jsonutils module is used instead of json - [N321] Validate that jsonutils module is used instead of json
- [N322] We do not use @authors tags in source files. We have git to track - [N322] We do not use @authors tags in source files. We have git to track
authorship. authorship.
- [N323] assert_called_once() is not a valid method
Creating Unit Tests Creating Unit Tests
------------------- -------------------

View File

@ -1,14 +0,0 @@
# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -28,6 +28,7 @@ from neutron.db.vpn import vpn_validator
from neutron.extensions import vpnaas from neutron.extensions import vpnaas
from neutron import manager from neutron import manager
from neutron.openstack.common import excutils from neutron.openstack.common import excutils
from neutron.openstack.common.gettextutils import _LW
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
from neutron.openstack.common import uuidutils from neutron.openstack.common import uuidutils
from neutron.plugins.common import constants from neutron.plugins.common import constants
@ -601,6 +602,16 @@ class VPNPluginDb(vpnaas.VPNPluginBase, base_db.CommonDbMixin):
router_id=router_id, router_id=router_id,
vpnservice_id=vpnservices[0]['id']) vpnservice_id=vpnservices[0]['id'])
def check_subnet_in_use(self, context, subnet_id):
with context.session.begin(subtransactions=True):
vpnservices = context.session.query(VPNService).filter_by(
subnet_id=subnet_id
).first()
if vpnservices:
raise vpnaas.SubnetInUseByVPNService(
subnet_id=subnet_id,
vpnservice_id=vpnservices['id'])
class VPNPluginRpcDbMixin(): class VPNPluginRpcDbMixin():
def _get_agent_hosting_vpn_services(self, context, host): def _get_agent_hosting_vpn_services(self, context, host):
@ -646,7 +657,7 @@ class VPNPluginRpcDbMixin():
vpnservice_db = self._get_vpnservice( vpnservice_db = self._get_vpnservice(
context, vpnservice['id']) context, vpnservice['id'])
except vpnaas.VPNServiceNotFound: except vpnaas.VPNServiceNotFound:
LOG.warn(_('vpnservice %s in db is already deleted'), LOG.warn(_LW('vpnservice %s in db is already deleted'),
vpnservice['id']) vpnservice['id'])
continue continue

View File

@ -1,14 +0,0 @@
# Copyright 2012 OpenStack Foundation.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -1,14 +0,0 @@
# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -130,15 +130,15 @@ class VPNAgent(l3_agent.L3NATAgentWithStateReport):
for device in self.devices: for device in self.devices:
device.destroy_router(router_id) device.destroy_router(router_id)
def _process_routers(self, routers, all_routers=False): def _process_router_if_compatible(self, router):
"""Router sync event. """Router sync event.
This method overwrites parent class method. This method overwrites parent class method.
:param routers: list of routers :param router: a router
""" """
super(VPNAgent, self)._process_routers(routers, all_routers) super(VPNAgent, self)._process_router_if_compatible(router)
for device in self.devices: for device in self.devices:
device.sync(self.context, routers) device.sync(self.context, [router])
def main(): def main():

View File

@ -1,14 +0,0 @@
# Copyright 2013, Nachi Ueno, NTT I3, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -19,6 +19,7 @@ import requests
from requests import exceptions as r_exc from requests import exceptions as r_exc
from neutron.openstack.common import jsonutils from neutron.openstack.common import jsonutils
from neutron.openstack.common.gettextutils import _LE, _LW
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
@ -84,7 +85,7 @@ class CsrRestClient(object):
and 'detail' fields). and 'detail' fields).
""" """
if method in ('POST', 'GET') and self.status == requests.codes.OK: if method in ('POST', 'GET') and self.status == requests.codes.OK:
LOG.debug(_('RESPONSE: %s'), response.json()) LOG.debug('RESPONSE: %s', response.json())
return response.json() return response.json()
if method == 'POST' and self.status == requests.codes.CREATED: if method == 'POST' and self.status == requests.codes.CREATED:
return response.headers.get('location', '') return response.headers.get('location', '')
@ -97,21 +98,21 @@ class CsrRestClient(object):
def _request(self, method, url, **kwargs): def _request(self, method, url, **kwargs):
"""Perform REST request and save response info.""" """Perform REST request and save response info."""
try: try:
LOG.debug(_("%(method)s: Request for %(resource)s payload: " LOG.debug("%(method)s: Request for %(resource)s payload: "
"%(payload)s"), "%(payload)s",
{'method': method.upper(), 'resource': url, {'method': method.upper(), 'resource': url,
'payload': kwargs.get('data')}) 'payload': kwargs.get('data')})
start_time = time.time() start_time = time.time()
response = self.session.request(method, url, verify=False, response = self.session.request(method, url, verify=False,
timeout=self.timeout, **kwargs) timeout=self.timeout, **kwargs)
LOG.debug(_("%(method)s Took %(time).2f seconds to process"), LOG.debug("%(method)s Took %(time).2f seconds to process",
{'method': method.upper(), {'method': method.upper(),
'time': time.time() - start_time}) 'time': time.time() - start_time})
except (r_exc.Timeout, r_exc.SSLError) as te: except (r_exc.Timeout, r_exc.SSLError) as te:
# Should never see SSLError, unless requests package is old (<2.0) # Should never see SSLError, unless requests package is old (<2.0)
timeout_val = 0.0 if self.timeout is None else self.timeout timeout_val = 0.0 if self.timeout is None else self.timeout
LOG.warning(_("%(method)s: Request timeout%(ssl)s " LOG.warning(_LW("%(method)s: Request timeout%(ssl)s "
"(%(timeout).3f sec) for CSR(%(host)s)"), "(%(timeout).3f sec) for CSR(%(host)s)"),
{'method': method, {'method': method,
'timeout': timeout_val, 'timeout': timeout_val,
'ssl': '(SSLError)' 'ssl': '(SSLError)'
@ -119,17 +120,18 @@ class CsrRestClient(object):
'host': self.host}) 'host': self.host})
self.status = requests.codes.REQUEST_TIMEOUT self.status = requests.codes.REQUEST_TIMEOUT
except r_exc.ConnectionError: except r_exc.ConnectionError:
LOG.exception(_("%(method)s: Unable to connect to CSR(%(host)s)"), LOG.exception(_LE("%(method)s: Unable to connect to "
"CSR(%(host)s)"),
{'method': method, 'host': self.host}) {'method': method, 'host': self.host})
self.status = requests.codes.NOT_FOUND self.status = requests.codes.NOT_FOUND
except Exception as e: except Exception as e:
LOG.error(_("%(method)s: Unexpected error for CSR (%(host)s): " LOG.error(_LE("%(method)s: Unexpected error for CSR (%(host)s): "
"%(error)s"), "%(error)s"),
{'method': method, 'host': self.host, 'error': e}) {'method': method, 'host': self.host, 'error': e})
self.status = requests.codes.INTERNAL_SERVER_ERROR self.status = requests.codes.INTERNAL_SERVER_ERROR
else: else:
self.status = response.status_code self.status = response.status_code
LOG.debug(_("%(method)s: Completed [%(status)s]"), LOG.debug("%(method)s: Completed [%(status)s]",
{'method': method, 'status': self.status}) {'method': method, 'status': self.status})
return self._response_info_for(response, method) return self._response_info_for(response, method)
@ -144,16 +146,16 @@ class CsrRestClient(object):
headers = {'Content-Length': '0', headers = {'Content-Length': '0',
'Accept': 'application/json'} 'Accept': 'application/json'}
headers.update(HEADER_CONTENT_TYPE_JSON) headers.update(HEADER_CONTENT_TYPE_JSON)
LOG.debug(_("%(auth)s with CSR %(host)s"), LOG.debug("%(auth)s with CSR %(host)s",
{'auth': 'Authenticating' if self.token is None {'auth': 'Authenticating' if self.token is None
else 'Reauthenticating', 'host': self.host}) else 'Reauthenticating', 'host': self.host})
self.token = None self.token = None
response = self._request("POST", url, headers=headers, auth=self.auth) response = self._request("POST", url, headers=headers, auth=self.auth)
if response: if response:
self.token = response['token-id'] self.token = response['token-id']
LOG.debug(_("Successfully authenticated with CSR %s"), self.host) LOG.debug("Successfully authenticated with CSR %s", self.host)
return True return True
LOG.error(_("Failed authentication with CSR %(host)s [%(status)s]"), LOG.error(_LE("Failed authentication with CSR %(host)s [%(status)s]"),
{'host': self.host, 'status': self.status}) {'host': self.host, 'status': self.status})
def _do_request(self, method, resource, payload=None, more_headers=None, def _do_request(self, method, resource, payload=None, more_headers=None,
@ -188,7 +190,7 @@ class CsrRestClient(object):
headers=headers) headers=headers)
if self.status != requests.codes.REQUEST_TIMEOUT: if self.status != requests.codes.REQUEST_TIMEOUT:
return response return response
LOG.error(_("%(method)s: Request timeout for CSR(%(host)s)"), LOG.error(_LE("%(method)s: Request timeout for CSR(%(host)s)"),
{'method': method, 'host': self.host}) {'method': method, 'host': self.host})
def get_request(self, resource, full_url=False): def get_request(self, resource, full_url=False):

View File

@ -23,6 +23,7 @@ import six
from neutron.common import exceptions from neutron.common import exceptions
from neutron.common import rpc as n_rpc from neutron.common import rpc as n_rpc
from neutron import context as ctx from neutron import context as ctx
from neutron.openstack.common.gettextutils import _LE, _LI, _LW
from neutron.openstack.common import lockutils from neutron.openstack.common import lockutils
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
from neutron.openstack.common import loopingcall from neutron.openstack.common import loopingcall
@ -125,7 +126,7 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
def vpnservice_updated(self, context, **kwargs): def vpnservice_updated(self, context, **kwargs):
"""Handle VPNaaS service driver change notifications.""" """Handle VPNaaS service driver change notifications."""
LOG.debug(_("Handling VPN service update notification '%s'"), LOG.debug("Handling VPN service update notification '%s'",
kwargs.get('reason', '')) kwargs.get('reason', ''))
self.sync(context, []) self.sync(context, [])
@ -147,20 +148,20 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
ipsec_conn = vpn_service.conn_state[conn_id] ipsec_conn = vpn_service.conn_state[conn_id]
config_changed = ipsec_conn.check_for_changes(conn_data) config_changed = ipsec_conn.check_for_changes(conn_data)
if config_changed: if config_changed:
LOG.debug(_("Update: Existing connection %s changed"), conn_id) LOG.debug("Update: Existing connection %s changed", conn_id)
ipsec_conn.delete_ipsec_site_connection(context, conn_id) ipsec_conn.delete_ipsec_site_connection(context, conn_id)
ipsec_conn.create_ipsec_site_connection(context, conn_data) ipsec_conn.create_ipsec_site_connection(context, conn_data)
ipsec_conn.conn_info = conn_data ipsec_conn.conn_info = conn_data
if ipsec_conn.forced_down: if ipsec_conn.forced_down:
if vpn_service.is_admin_up and conn_is_admin_up: if vpn_service.is_admin_up and conn_is_admin_up:
LOG.debug(_("Update: Connection %s no longer admin down"), LOG.debug("Update: Connection %s no longer admin down",
conn_id) conn_id)
ipsec_conn.set_admin_state(is_up=True) ipsec_conn.set_admin_state(is_up=True)
ipsec_conn.forced_down = False ipsec_conn.forced_down = False
else: else:
if not vpn_service.is_admin_up or not conn_is_admin_up: if not vpn_service.is_admin_up or not conn_is_admin_up:
LOG.debug(_("Update: Connection %s forced to admin down"), LOG.debug("Update: Connection %s forced to admin down",
conn_id) conn_id)
ipsec_conn.set_admin_state(is_up=False) ipsec_conn.set_admin_state(is_up=False)
ipsec_conn.forced_down = True ipsec_conn.forced_down = True
@ -168,12 +169,12 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
ipsec_conn = vpn_service.create_connection(conn_data) ipsec_conn = vpn_service.create_connection(conn_data)
ipsec_conn.create_ipsec_site_connection(context, conn_data) ipsec_conn.create_ipsec_site_connection(context, conn_data)
if not vpn_service.is_admin_up or not conn_is_admin_up: if not vpn_service.is_admin_up or not conn_is_admin_up:
LOG.debug(_("Update: Created new connection %s in admin down " LOG.debug("Update: Created new connection %s in admin down "
"state"), conn_id) "state", conn_id)
ipsec_conn.set_admin_state(is_up=False) ipsec_conn.set_admin_state(is_up=False)
ipsec_conn.forced_down = True ipsec_conn.forced_down = True
else: else:
LOG.debug(_("Update: Created new connection %s"), conn_id) LOG.debug("Update: Created new connection %s", conn_id)
ipsec_conn.is_dirty = False ipsec_conn.is_dirty = False
ipsec_conn.last_status = conn_data['status'] ipsec_conn.last_status = conn_data['status']
@ -184,11 +185,11 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
"""Handle notification for a single VPN Service and its connections.""" """Handle notification for a single VPN Service and its connections."""
vpn_service_id = service_data['id'] vpn_service_id = service_data['id']
if vpn_service_id in self.service_state: if vpn_service_id in self.service_state:
LOG.debug(_("Update: Existing VPN service %s detected"), LOG.debug("Update: Existing VPN service %s detected",
vpn_service_id) vpn_service_id)
vpn_service = self.service_state[vpn_service_id] vpn_service = self.service_state[vpn_service_id]
else: else:
LOG.debug(_("Update: New VPN service %s detected"), vpn_service_id) LOG.debug("Update: New VPN service %s detected", vpn_service_id)
vpn_service = self.create_vpn_service(service_data) vpn_service = self.create_vpn_service(service_data)
if not vpn_service: if not vpn_service:
return return
@ -199,7 +200,7 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
vpn_service.is_admin_up = service_data[u'admin_state_up'] vpn_service.is_admin_up = service_data[u'admin_state_up']
for conn_data in service_data['ipsec_conns']: for conn_data in service_data['ipsec_conns']:
self.update_connection(context, vpn_service_id, conn_data) self.update_connection(context, vpn_service_id, conn_data)
LOG.debug(_("Update: Completed update processing")) LOG.debug("Update: Completed update processing")
return vpn_service return vpn_service
def update_all_services_and_connections(self, context): def update_all_services_and_connections(self, context):
@ -229,9 +230,9 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
for conn_id in service_state.conn_state: for conn_id in service_state.conn_state:
service_state.conn_state[conn_id].is_dirty = True service_state.conn_state[conn_id].is_dirty = True
connection_count += 1 connection_count += 1
LOG.debug(_("Mark: %(service)d VPN services and %(conn)d IPSec " LOG.debug("Mark: %(service)d VPN services and %(conn)d IPSec "
"connections marked dirty"), {'service': service_count, "connections marked dirty", {'service': service_count,
'conn': connection_count}) 'conn': connection_count})
def remove_unknown_connections(self, context): def remove_unknown_connections(self, context):
"""Remove connections that are not known by service driver.""" """Remove connections that are not known by service driver."""
@ -251,8 +252,8 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
del self.service_state[vpn_service_id] del self.service_state[vpn_service_id]
elif dirty: elif dirty:
self.connections_removed = True self.connections_removed = True
LOG.debug(_("Sweep: Removed %(service)d dirty VPN service%(splural)s " LOG.debug("Sweep: Removed %(service)d dirty VPN service%(splural)s "
"and %(conn)d dirty IPSec connection%(cplural)s"), "and %(conn)d dirty IPSec connection%(cplural)s",
{'service': service_count, 'conn': connection_count, {'service': service_count, 'conn': connection_count,
'splural': 's'[service_count == 1:], 'splural': 's'[service_count == 1:],
'cplural': 's'[connection_count == 1:]}) 'cplural': 's'[connection_count == 1:]})
@ -266,22 +267,22 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
report info will be created for the connection. The combined report report info will be created for the connection. The combined report
data is returned. data is returned.
""" """
LOG.debug(_("Report: Collecting status for IPSec connections on VPN " LOG.debug("Report: Collecting status for IPSec connections on VPN "
"service %s"), vpn_service.service_id) "service %s", vpn_service.service_id)
tunnels = vpn_service.get_ipsec_connections_status() tunnels = vpn_service.get_ipsec_connections_status()
report = {} report = {}
for connection in vpn_service.conn_state.values(): for connection in vpn_service.conn_state.values():
if connection.forced_down: if connection.forced_down:
LOG.debug(_("Connection %s forced down"), connection.conn_id) LOG.debug("Connection %s forced down", connection.conn_id)
current_status = constants.DOWN current_status = constants.DOWN
else: else:
current_status = connection.find_current_status_in(tunnels) current_status = connection.find_current_status_in(tunnels)
LOG.debug(_("Connection %(conn)s reported %(status)s"), LOG.debug("Connection %(conn)s reported %(status)s",
{'conn': connection.conn_id, {'conn': connection.conn_id,
'status': current_status}) 'status': current_status})
frag = connection.update_status_and_build_report(current_status) frag = connection.update_status_and_build_report(current_status)
if frag: if frag:
LOG.debug(_("Report: Adding info for IPSec connection %s"), LOG.debug("Report: Adding info for IPSec connection %s",
connection.conn_id) connection.conn_id)
report.update(frag) report.update(frag)
return report return report
@ -301,7 +302,7 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
pending_handled = plugin_utils.in_pending_status( pending_handled = plugin_utils.in_pending_status(
vpn_service.last_status) vpn_service.last_status)
vpn_service.update_last_status() vpn_service.update_last_status()
LOG.debug(_("Report: Adding info for VPN service %s"), LOG.debug("Report: Adding info for VPN service %s",
vpn_service.service_id) vpn_service.service_id)
return {u'id': vpn_service.service_id, return {u'id': vpn_service.service_id,
u'status': vpn_service.last_status, u'status': vpn_service.last_status,
@ -323,17 +324,17 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
def report_status_internal(self, context): def report_status_internal(self, context):
"""Generate report and send to plugin, if anything changed.""" """Generate report and send to plugin, if anything changed."""
service_report = [] service_report = []
LOG.debug(_("Report: Starting status report processing")) LOG.debug("Report: Starting status report processing")
for vpn_service_id, vpn_service in self.service_state.items(): for vpn_service_id, vpn_service in self.service_state.items():
LOG.debug(_("Report: Collecting status for VPN service %s"), LOG.debug("Report: Collecting status for VPN service %s",
vpn_service_id) vpn_service_id)
report = self.build_report_for_service(vpn_service) report = self.build_report_for_service(vpn_service)
if report: if report:
service_report.append(report) service_report.append(report)
if service_report: if service_report:
LOG.info(_("Sending status report update to plugin")) LOG.info(_LI("Sending status report update to plugin"))
self.agent_rpc.update_status(context, service_report) self.agent_rpc.update_status(context, service_report)
LOG.debug(_("Report: Completed status report processing")) LOG.debug("Report: Completed status report processing")
return service_report return service_report
@lockutils.synchronized('vpn-agent', 'neutron-') @lockutils.synchronized('vpn-agent', 'neutron-')
@ -617,8 +618,8 @@ class CiscoCsrIPSecConnection(object):
LOG.debug("%(resource)s %(which)s is configured", LOG.debug("%(resource)s %(which)s is configured",
{'resource': resource, 'which': which}) {'resource': resource, 'which': which})
return return
LOG.error(_("Unable to create %(resource)s %(which)s: " LOG.error(_LE("Unable to create %(resource)s %(which)s: "
"%(status)d"), "%(status)d"),
{'resource': resource, 'which': which, {'resource': resource, 'which': which,
'status': self.csr.status}) 'status': self.csr.status})
# ToDO(pcm): Set state to error # ToDO(pcm): Set state to error
@ -630,7 +631,7 @@ class CiscoCsrIPSecConnection(object):
try: try:
getattr(self.csr, create_action)(info) getattr(self.csr, create_action)(info)
except AttributeError: except AttributeError:
LOG.exception(_("Internal error - '%s' is not defined"), LOG.exception(_LE("Internal error - '%s' is not defined"),
create_action) create_action)
raise CsrResourceCreateFailure(resource=title, raise CsrResourceCreateFailure(resource=title,
which=resource_id) which=resource_id)
@ -643,22 +644,22 @@ class CiscoCsrIPSecConnection(object):
LOG.debug("%(resource)s configuration %(which)s was removed", LOG.debug("%(resource)s configuration %(which)s was removed",
{'resource': resource, 'which': which}) {'resource': resource, 'which': which})
else: else:
LOG.warning(_("Unable to delete %(resource)s %(which)s: " LOG.warning(_LW("Unable to delete %(resource)s %(which)s: "
"%(status)d"), {'resource': resource, "%(status)d"), {'resource': resource,
'which': which, 'which': which,
'status': status}) 'status': status})
def do_rollback(self): def do_rollback(self):
"""Undo create steps that were completed successfully.""" """Undo create steps that were completed successfully."""
for step in reversed(self.steps): for step in reversed(self.steps):
delete_action = 'delete_%s' % step.action delete_action = 'delete_%s' % step.action
LOG.debug(_("Performing rollback action %(action)s for " LOG.debug("Performing rollback action %(action)s for "
"resource %(resource)s"), {'action': delete_action, "resource %(resource)s", {'action': delete_action,
'resource': step.title}) 'resource': step.title})
try: try:
getattr(self.csr, delete_action)(step.resource_id) getattr(self.csr, delete_action)(step.resource_id)
except AttributeError: except AttributeError:
LOG.exception(_("Internal error - '%s' is not defined"), LOG.exception(_LE("Internal error - '%s' is not defined"),
delete_action) delete_action)
raise CsrResourceCreateFailure(resource=step.title, raise CsrResourceCreateFailure(resource=step.title,
which=step.resource_id) which=step.resource_id)
@ -678,7 +679,7 @@ class CiscoCsrIPSecConnection(object):
ike_policy_id = conn_info['cisco']['ike_policy_id'] ike_policy_id = conn_info['cisco']['ike_policy_id']
ipsec_policy_id = conn_info['cisco']['ipsec_policy_id'] ipsec_policy_id = conn_info['cisco']['ipsec_policy_id']
LOG.debug(_('Creating IPSec connection %s'), conn_id) LOG.debug('Creating IPSec connection %s', conn_id)
# Get all the attributes needed to create # Get all the attributes needed to create
try: try:
psk_info = self.create_psk_info(psk_id, conn_info) psk_info = self.create_psk_info(psk_id, conn_info)
@ -711,10 +712,10 @@ class CiscoCsrIPSecConnection(object):
route_id, 'Static Route') route_id, 'Static Route')
except CsrResourceCreateFailure: except CsrResourceCreateFailure:
self.do_rollback() self.do_rollback()
LOG.info(_("FAILED: Create of IPSec site-to-site connection %s"), LOG.info(_LI("FAILED: Create of IPSec site-to-site connection %s"),
conn_id) conn_id)
else: else:
LOG.info(_("SUCCESS: Created IPSec site-to-site connection %s"), LOG.info(_LI("SUCCESS: Created IPSec site-to-site connection %s"),
conn_id) conn_id)
def delete_ipsec_site_connection(self, context, conn_id): def delete_ipsec_site_connection(self, context, conn_id):
@ -723,13 +724,13 @@ class CiscoCsrIPSecConnection(object):
This will be best effort and will continue, if there are any This will be best effort and will continue, if there are any
failures. failures.
""" """
LOG.debug(_('Deleting IPSec connection %s'), conn_id) LOG.debug('Deleting IPSec connection %s', conn_id)
if not self.steps: if not self.steps:
LOG.warning(_('Unable to find connection %s'), conn_id) LOG.warning(_LW('Unable to find connection %s'), conn_id)
else: else:
self.do_rollback() self.do_rollback()
LOG.info(_("SUCCESS: Deleted IPSec site-to-site connection %s"), LOG.info(_LI("SUCCESS: Deleted IPSec site-to-site connection %s"),
conn_id) conn_id)
def set_admin_state(self, is_up): def set_admin_state(self, is_up):
@ -737,6 +738,7 @@ class CiscoCsrIPSecConnection(object):
self.csr.set_ipsec_connection_state(self.tunnel, admin_up=is_up) self.csr.set_ipsec_connection_state(self.tunnel, admin_up=is_up)
if self.csr.status != requests.codes.NO_CONTENT: if self.csr.status != requests.codes.NO_CONTENT:
state = "UP" if is_up else "DOWN" state = "UP" if is_up else "DOWN"
LOG.error(_("Unable to change %(tunnel)s admin state to " LOG.error(_LE("Unable to change %(tunnel)s admin state to "
"%(state)s"), {'tunnel': self.tunnel, 'state': state}) "%(state)s"), {'tunnel': self.tunnel,
'state': state})
raise CsrAdminStateChangeFailure(tunnel=self.tunnel, state=state) raise CsrAdminStateChangeFailure(tunnel=self.tunnel, state=state)

View File

@ -28,6 +28,7 @@ from neutron.agent.linux import ip_lib
from neutron.agent.linux import utils from neutron.agent.linux import utils
from neutron.common import rpc as n_rpc from neutron.common import rpc as n_rpc
from neutron import context from neutron import context
from neutron.openstack.common.gettextutils import _LE
from neutron.openstack.common import lockutils from neutron.openstack.common import lockutils
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
from neutron.openstack.common import loopingcall from neutron.openstack.common import loopingcall
@ -244,7 +245,7 @@ class BaseSwanProcess():
self.start() self.start()
except RuntimeError: except RuntimeError:
LOG.exception( LOG.exception(
_("Failed to enable vpn process on router %s"), _LE("Failed to enable vpn process on router %s"),
self.id) self.id)
def disable(self): def disable(self):
@ -255,7 +256,7 @@ class BaseSwanProcess():
self.remove_config() self.remove_config()
except RuntimeError: except RuntimeError:
LOG.exception( LOG.exception(
_("Failed to disable vpn process on router %s"), _LE("Failed to disable vpn process on router %s"),
self.id) self.id)
@abc.abstractmethod @abc.abstractmethod

View File

@ -15,6 +15,7 @@
# under the License. # under the License.
from neutron.db.vpn import vpn_db from neutron.db.vpn import vpn_db
from neutron.openstack.common.gettextutils import _LI
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
from neutron.plugins.common import constants from neutron.plugins.common import constants
from neutron.services import service_base from neutron.services import service_base
@ -41,7 +42,7 @@ class VPNDriverPlugin(VPNPlugin, vpn_db.VPNPluginRpcDbMixin):
# Load the service driver from neutron.conf. # Load the service driver from neutron.conf.
drivers, default_provider = service_base.load_drivers( drivers, default_provider = service_base.load_drivers(
constants.VPN, self) constants.VPN, self)
LOG.info(_("VPN plugin using service driver: %s"), default_provider) LOG.info(_LI("VPN plugin using service driver: %s"), default_provider)
self.ipsec_driver = drivers[default_provider] self.ipsec_driver = drivers[default_provider]
def _get_driver_for_vpnservice(self, vpnservice): def _get_driver_for_vpnservice(self, vpnservice):

View File

@ -94,8 +94,8 @@ class BaseIPsecVpnAgentApi(n_rpc.RpcProxy):
admin_state_up=True, admin_state_up=True,
active=True) active=True)
for l3_agent in l3_agents: for l3_agent in l3_agents:
LOG.debug(_('Notify agent at %(topic)s.%(host)s the message ' LOG.debug('Notify agent at %(topic)s.%(host)s the message '
'%(method)s %(args)s'), '%(method)s %(args)s',
{'topic': self.topic, {'topic': self.topic,
'host': l3_agent.host, 'host': l3_agent.host,
'method': method, 'method': method,

View File

@ -32,8 +32,7 @@ from oslo.config import cfg
from neutron.db import l3_db from neutron.db import l3_db
from neutron.db import models_v2 from neutron.db import models_v2
from neutron.openstack.common.gettextutils import _LE from neutron.openstack.common.gettextutils import _LE, _LI
from neutron.openstack.common.gettextutils import _LI
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
from neutron.services.vpn.device_drivers import ( from neutron.services.vpn.device_drivers import (
cisco_csr_rest_client as csr_client) cisco_csr_rest_client as csr_client)
@ -103,8 +102,8 @@ def get_available_csrs_from_config(config_files):
try: try:
netaddr.IPAddress(rest_mgmt_ip) netaddr.IPAddress(rest_mgmt_ip)
except netaddr.core.AddrFormatError: except netaddr.core.AddrFormatError:
LOG.error(_("Ignoring Cisco CSR for subnet %s - " LOG.error(_LE("Ignoring Cisco CSR for subnet %s - "
"REST management is not an IP address"), "REST management is not an IP address"),
for_router) for_router)
continue continue
try: try:

View File

@ -20,6 +20,7 @@ from neutron.common import exceptions
from neutron.db import model_base from neutron.db import model_base
from neutron.db import models_v2 from neutron.db import models_v2
from neutron.db.vpn import vpn_db from neutron.db.vpn import vpn_db
from neutron.openstack.common.gettextutils import _LI
from neutron.openstack.common import log as logging from neutron.openstack.common import log as logging
LOG = logging.getLogger(__name__) LOG = logging.getLogger(__name__)
@ -156,10 +157,10 @@ def determine_csr_policy_id(policy_type, conn_policy_field, map_policy_field,
then call lookup_policy() to find the current mapping for that ID. then call lookup_policy() to find the current mapping for that ID.
""" """
csr_id = get_next_available_id(session, map_policy_field, policy_type) csr_id = get_next_available_id(session, map_policy_field, policy_type)
LOG.debug(_("Reserved new CSR ID %(csr_id)d for %(policy)s " LOG.debug("Reserved new CSR ID %(csr_id)d for %(policy)s "
"ID %(policy_id)s"), {'csr_id': csr_id, "ID %(policy_id)s", {'csr_id': csr_id,
'policy': policy_type, 'policy': policy_type,
'policy_id': policy_id}) 'policy_id': policy_id})
return csr_id return csr_id
@ -183,9 +184,9 @@ def get_tunnel_mapping_for(conn_id, session):
try: try:
entry = session.query(IdentifierMap).filter_by( entry = session.query(IdentifierMap).filter_by(
ipsec_site_conn_id=conn_id).one() ipsec_site_conn_id=conn_id).one()
LOG.debug(_("Mappings for IPSec connection %(conn)s - " LOG.debug("Mappings for IPSec connection %(conn)s - "
"tunnel=%(tunnel)s ike_policy=%(csr_ike)d " "tunnel=%(tunnel)s ike_policy=%(csr_ike)d "
"ipsec_policy=%(csr_ipsec)d"), "ipsec_policy=%(csr_ipsec)d",
{'conn': conn_id, 'tunnel': entry.csr_tunnel_id, {'conn': conn_id, 'tunnel': entry.csr_tunnel_id,
'csr_ike': entry.csr_ike_policy_id, 'csr_ike': entry.csr_ike_policy_id,
'csr_ipsec': entry.csr_ipsec_policy_id}) 'csr_ipsec': entry.csr_ipsec_policy_id})
@ -222,9 +223,9 @@ def create_tunnel_mapping(context, conn_info):
msg = _("Attempt to create duplicate entry in Cisco CSR " msg = _("Attempt to create duplicate entry in Cisco CSR "
"mapping table for connection %s") % conn_id "mapping table for connection %s") % conn_id
raise CsrInternalError(reason=msg) raise CsrInternalError(reason=msg)
LOG.info(_("Mapped connection %(conn_id)s to Tunnel%(tunnel_id)d " LOG.info(_LI("Mapped connection %(conn_id)s to Tunnel%(tunnel_id)d "
"using IKE policy ID %(ike_id)d and IPSec policy " "using IKE policy ID %(ike_id)d and IPSec policy "
"ID %(ipsec_id)d"), "ID %(ipsec_id)d"),
{'conn_id': conn_id, 'tunnel_id': csr_tunnel_id, {'conn_id': conn_id, 'tunnel_id': csr_tunnel_id,
'ike_id': csr_ike_id, 'ipsec_id': csr_ipsec_id}) 'ike_id': csr_ike_id, 'ipsec_id': csr_ipsec_id})
@ -234,4 +235,4 @@ def delete_tunnel_mapping(context, conn_info):
with context.session.begin(): with context.session.begin():
sess_qry = context.session.query(IdentifierMap) sess_qry = context.session.query(IdentifierMap)
sess_qry.filter_by(ipsec_site_conn_id=conn_id).delete() sess_qry.filter_by(ipsec_site_conn_id=conn_id).delete()
LOG.info(_("Removed mapping for connection %s"), conn_id) LOG.info(_LI("Removed mapping for connection %s"), conn_id)

View File

@ -101,8 +101,8 @@ class CiscoCsrIPsecVpnAgentApi(service_drivers.BaseIPsecVpnAgentApi,
# NOTE: This is a config error for workaround. At this point we # NOTE: This is a config error for workaround. At this point we
# can't set state of resource to error. # can't set state of resource to error.
return return
LOG.debug(_('Notify agent at %(topic)s.%(host)s the message ' LOG.debug('Notify agent at %(topic)s.%(host)s the message '
'%(method)s %(args)s for router %(router)s'), '%(method)s %(args)s for router %(router)s',
{'topic': self.topic, {'topic': self.topic,
'host': host, 'host': host,
'method': method, 'method': method,

View File

@ -1,13 +0,0 @@
# Copyright 2013 OpenStack Foundation
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -1,14 +0,0 @@
# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -434,7 +434,7 @@ class VPNPluginDbTestCase(VPNTestMixin,
service_plugins=service_plugins service_plugins=service_plugins
) )
self._subnet_id = uuidutils.generate_uuid() self._subnet_id = uuidutils.generate_uuid()
self.core_plugin = TestVpnCorePlugin self.core_plugin = TestVpnCorePlugin()
self.plugin = vpn_plugin.VPNPlugin() self.plugin = vpn_plugin.VPNPlugin()
ext_mgr = api_extensions.PluginAwareExtensionManager( ext_mgr = api_extensions.PluginAwareExtensionManager(
extensions_path, extensions_path,
@ -867,6 +867,55 @@ class TestVpnaas(VPNPluginDbTestCase):
if k in expected), if k in expected),
expected) expected)
def test_delete_router_interface_in_use_by_vpnservice(self):
"""Test delete router interface in use by vpn service."""
with self.subnet(cidr='10.2.0.0/24') as subnet:
with self.router() as router:
with self.vpnservice(subnet=subnet,
router=router):
self._router_interface_action('remove',
router['router']['id'],
subnet['subnet']['id'],
None,
expected_code=webob.exc.
HTTPConflict.code)
def test_delete_external_gateway_interface_in_use_by_vpnservice(self):
"""Test delete external gateway interface in use by vpn service."""
with self.subnet(cidr='10.2.0.0/24') as subnet:
with self.router() as router:
with self.subnet(cidr='11.0.0.0/24') as public_sub:
self._set_net_external(
public_sub['subnet']['network_id'])
self._add_external_gateway_to_router(
router['router']['id'],
public_sub['subnet']['network_id'])
with self.vpnservice(subnet=subnet,
router=router):
self._remove_external_gateway_from_router(
router['router']['id'],
public_sub['subnet']['network_id'],
expected_code=webob.exc.HTTPConflict.code)
def test_router_update_after_ipsec_site_connection(self):
"""Test case to update router after vpn connection."""
rname1 = "router_one"
rname2 = "router_two"
with self.subnet(cidr='10.2.0.0/24') as subnet:
with self.router(name=rname1) as r:
with self.vpnservice(subnet=subnet,
router=r
) as vpnservice:
self.ipsec_site_connection(
name='connection1', vpnservice=vpnservice
)
body = self._show('routers', r['router']['id'])
self.assertEqual(body['router']['name'], rname1)
body = self._update('routers', r['router']['id'],
{'router': {'name': rname2}})
body = self._show('routers', r['router']['id'])
self.assertEqual(body['router']['name'], rname2)
def test_update_vpnservice(self): def test_update_vpnservice(self):
"""Test case to update a vpnservice.""" """Test case to update a vpnservice."""
name = 'new_vpnservice1' name = 'new_vpnservice1'

View File

@ -1,13 +0,0 @@
# Copyright 2013 New Dream Network, LLC (DreamHost)
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -1,14 +0,0 @@
# (c) Copyright 2013 Hewlett-Packard Development Company, L.P.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -1,14 +0,0 @@
# Copyright 2013, Nachi Ueno, NTT I3, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -1,577 +0,0 @@
# Copyright 2014 Cisco Systems, Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
"""Mock REST requests to Cisco Cloud Services Router."""
import re
import functools
# TODO(pcm): Remove when switch to requests-mock package. Comment out, if use
# local copy of httmock.py source. Needed for PEP8.
import httmock
import requests
from requests import exceptions as r_exc
from neutron.openstack.common import log as logging
# TODO(pcm) Remove once httmock package is added to test-requirements. For
# now, uncomment and include httmock source to unit test.
# from neutron.tests.unit.services.vpn.device_drivers import httmock
LOG = logging.getLogger(__name__)
def repeat(n):
"""Decorator to limit the number of times a handler is called.
Will allow the wrapped function (handler) to be called 'n' times.
After that, this will return None for any additional calls,
allowing other handlers, if any, to be invoked.
"""
class static:
retries = n
def decorator(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
if static.retries == 0:
return None
static.retries -= 1
return func(*args, **kwargs)
return wrapped
return decorator
def filter_request(methods, resource):
"""Decorator to invoke handler once for a specific resource.
This will call the handler only for a specific resource using
a specific method(s). Any other resource request or method will
return None, allowing other handlers, if any, to be invoked.
"""
class static:
target_methods = [m.upper() for m in methods]
target_resource = resource
def decorator(func):
@functools.wraps(func)
def wrapped(*args, **kwargs):
if (args[1].method in static.target_methods and
static.target_resource in args[0].path):
return func(*args, **kwargs)
else:
return None # Not for this resource
return wrapped
return decorator
@httmock.urlmatch(netloc=r'localhost')
def token(url, request):
if 'auth/token-services' in url.path:
return {'status_code': requests.codes.OK,
'content': {'token-id': 'dummy-token'}}
@httmock.urlmatch(netloc=r'localhost')
def token_unauthorized(url, request):
if 'auth/token-services' in url.path:
return {'status_code': requests.codes.UNAUTHORIZED}
@httmock.urlmatch(netloc=r'wrong-host')
def token_wrong_host(url, request):
raise r_exc.ConnectionError()
@httmock.all_requests
def token_timeout(url, request):
raise r_exc.Timeout()
@filter_request(['get'], 'global/host-name')
@httmock.all_requests
def timeout(url, request):
"""Simulated timeout of a normal request."""
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
raise r_exc.Timeout()
@httmock.urlmatch(netloc=r'localhost')
def no_such_resource(url, request):
"""Indicate not found error, when invalid resource requested."""
return {'status_code': requests.codes.NOT_FOUND}
@filter_request(['get'], 'global/host-name')
@repeat(1)
@httmock.urlmatch(netloc=r'localhost')
def expired_request(url, request):
"""Simulate access denied failure on first request for this resource.
Intent here is to simulate that the token has expired, by failing
the first request to the resource. Because of the repeat=1, this
will only be called once, and subsequent calls will not be handled
by this function, but instead will access the normal handler and
will pass. Currently configured for a GET request, but will work
with POST and PUT as well. For DELETE, would need to filter_request on a
different resource (e.g. 'global/local-users')
"""
return {'status_code': requests.codes.UNAUTHORIZED}
@httmock.urlmatch(netloc=r'localhost')
def normal_get(url, request):
if request.method != 'GET':
return
LOG.debug("GET mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
if 'global/host-name' in url.path:
content = {u'kind': u'object#host-name',
u'host-name': u'Router'}
return httmock.response(requests.codes.OK, content=content)
if 'global/local-users' in url.path:
content = {u'kind': u'collection#local-user',
u'users': ['peter', 'paul', 'mary']}
return httmock.response(requests.codes.OK, content=content)
if 'interfaces/GigabitEthernet' in url.path:
actual_interface = url.path.split('/')[-1]
ip = actual_interface[-1]
content = {u'kind': u'object#interface',
u'description': u'Changed description',
u'if-name': actual_interface,
u'proxy-arp': True,
u'subnet-mask': u'255.255.255.0',
u'icmp-unreachable': True,
u'nat-direction': u'',
u'icmp-redirects': True,
u'ip-address': u'192.168.200.%s' % ip,
u'verify-unicast-source': False,
u'type': u'ethernet'}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/ike/policies/2' in url.path:
content = {u'kind': u'object#ike-policy',
u'priority-id': u'2',
u'version': u'v1',
u'local-auth-method': u'pre-share',
u'encryption': u'aes256',
u'hash': u'sha',
u'dhGroup': 5,
u'lifetime': 3600}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/ike/keyrings' in url.path:
content = {u'kind': u'object#ike-keyring',
u'keyring-name': u'5',
u'pre-shared-key-list': [
{u'key': u'super-secret',
u'encrypted': False,
u'peer-address': u'10.10.10.20 255.255.255.0'}
]}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/ipsec/policies/' in url.path:
ipsec_policy_id = url.path.split('/')[-1]
content = {u'kind': u'object#ipsec-policy',
u'mode': u'tunnel',
u'policy-id': u'%s' % ipsec_policy_id,
u'protection-suite': {
u'esp-encryption': u'esp-256-aes',
u'esp-authentication': u'esp-sha-hmac',
u'ah': u'ah-sha-hmac',
},
u'anti-replay-window-size': u'Disable',
u'lifetime-sec': 120,
u'pfs': u'group5',
u'lifetime-kb': 4608000,
u'idle-time': None}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/site-to-site/Tunnel' in url.path:
tunnel = url.path.split('/')[-1]
# Use same number, to allow mock to generate IPSec policy ID
ipsec_policy_id = tunnel[6:]
content = {u'kind': u'object#vpn-site-to-site',
u'vpn-interface-name': u'%s' % tunnel,
u'ip-version': u'ipv4',
u'vpn-type': u'site-to-site',
u'ipsec-policy-id': u'%s' % ipsec_policy_id,
u'ike-profile-id': None,
u'mtu': 1500,
u'local-device': {
u'ip-address': '10.3.0.1/24',
u'tunnel-ip-address': '10.10.10.10'
},
u'remote-device': {
u'tunnel-ip-address': '10.10.10.20'
}}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/ike/keepalive' in url.path:
content = {u'interval': 60,
u'retry': 4,
u'periodic': True}
return httmock.response(requests.codes.OK, content=content)
if 'routing-svc/static-routes' in url.path:
content = {u'destination-network': u'10.1.0.0/24',
u'kind': u'object#static-route',
u'next-hop-router': None,
u'outgoing-interface': u'GigabitEthernet1',
u'admin-distance': 1}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/site-to-site/active/sessions' in url.path:
# Only including needed fields for mock
content = {u'kind': u'collection#vpn-active-sessions',
u'items': [{u'status': u'DOWN-NEGOTIATING',
u'vpn-interface-name': u'Tunnel123'}, ]}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/ike/keyrings')
@httmock.urlmatch(netloc=r'localhost')
def get_fqdn(url, request):
LOG.debug("GET FQDN mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
content = {u'kind': u'object#ike-keyring',
u'keyring-name': u'5',
u'pre-shared-key-list': [
{u'key': u'super-secret',
u'encrypted': False,
u'peer-address': u'cisco.com'}
]}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/ipsec/policies/')
@httmock.urlmatch(netloc=r'localhost')
def get_no_ah(url, request):
LOG.debug("GET No AH mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
ipsec_policy_id = url.path.split('/')[-1]
content = {u'kind': u'object#ipsec-policy',
u'mode': u'tunnel',
u'anti-replay-window-size': u'128',
u'policy-id': u'%s' % ipsec_policy_id,
u'protection-suite': {
u'esp-encryption': u'esp-aes',
u'esp-authentication': u'esp-sha-hmac',
},
u'lifetime-sec': 120,
u'pfs': u'group5',
u'lifetime-kb': 4608000,
u'idle-time': None}
return httmock.response(requests.codes.OK, content=content)
@httmock.urlmatch(netloc=r'localhost')
def get_defaults(url, request):
if request.method != 'GET':
return
LOG.debug("GET mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
if 'vpn-svc/ike/policies/2' in url.path:
content = {u'kind': u'object#ike-policy',
u'priority-id': u'2',
u'version': u'v1',
u'local-auth-method': u'pre-share',
u'encryption': u'des',
u'hash': u'sha',
u'dhGroup': 1,
u'lifetime': 86400}
return httmock.response(requests.codes.OK, content=content)
if 'vpn-svc/ipsec/policies/' in url.path:
ipsec_policy_id = url.path.split('/')[-1]
content = {u'kind': u'object#ipsec-policy',
u'mode': u'tunnel',
u'policy-id': u'%s' % ipsec_policy_id,
u'protection-suite': {},
u'lifetime-sec': 3600,
u'pfs': u'Disable',
u'anti-replay-window-size': u'None',
u'lifetime-kb': 4608000,
u'idle-time': None}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/site-to-site')
@httmock.urlmatch(netloc=r'localhost')
def get_unnumbered(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
tunnel = url.path.split('/')[-1]
ipsec_policy_id = tunnel[6:]
content = {u'kind': u'object#vpn-site-to-site',
u'vpn-interface-name': u'%s' % tunnel,
u'ip-version': u'ipv4',
u'vpn-type': u'site-to-site',
u'ipsec-policy-id': u'%s' % ipsec_policy_id,
u'ike-profile-id': None,
u'mtu': 1500,
u'local-device': {
u'ip-address': u'GigabitEthernet3',
u'tunnel-ip-address': u'10.10.10.10'
},
u'remote-device': {
u'tunnel-ip-address': u'10.10.10.20'
}}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/site-to-site/Tunnel')
@httmock.urlmatch(netloc=r'localhost')
def get_admin_down(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
# URI has .../Tunnel#/state, so get number from 2nd to last element
tunnel = url.path.split('/')[-2]
content = {u'kind': u'object#vpn-site-to-site-state',
u'vpn-interface-name': u'%s' % tunnel,
u'line-protocol-state': u'down',
u'enabled': False}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/site-to-site/Tunnel')
@httmock.urlmatch(netloc=r'localhost')
def get_admin_up(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
# URI has .../Tunnel#/state, so get number from 2nd to last element
tunnel = url.path.split('/')[-2]
content = {u'kind': u'object#vpn-site-to-site-state',
u'vpn-interface-name': u'%s' % tunnel,
u'line-protocol-state': u'down',
u'enabled': True}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/site-to-site')
@httmock.urlmatch(netloc=r'localhost')
def get_mtu(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
tunnel = url.path.split('/')[-1]
ipsec_policy_id = tunnel[6:]
content = {u'kind': u'object#vpn-site-to-site',
u'vpn-interface-name': u'%s' % tunnel,
u'ip-version': u'ipv4',
u'vpn-type': u'site-to-site',
u'ipsec-policy-id': u'%s' % ipsec_policy_id,
u'ike-profile-id': None,
u'mtu': 9192,
u'local-device': {
u'ip-address': u'10.3.0.1/24',
u'tunnel-ip-address': u'10.10.10.10'
},
u'remote-device': {
u'tunnel-ip-address': u'10.10.10.20'
}}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'vpn-svc/ike/keepalive')
@httmock.urlmatch(netloc=r'localhost')
def get_not_configured(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.NOT_FOUND}
@filter_request(['get'], 'vpn-svc/site-to-site/active/sessions')
@httmock.urlmatch(netloc=r'localhost')
def get_none(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
content = {u'kind': u'collection#vpn-active-sessions',
u'items': []}
return httmock.response(requests.codes.OK, content=content)
@filter_request(['get'], 'interfaces/GigabitEthernet3')
@httmock.urlmatch(netloc=r'localhost')
def get_local_ip(url, request):
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
content = {u'kind': u'object#interface',
u'subnet-mask': u'255.255.255.0',
u'ip-address': u'10.5.0.2'}
return httmock.response(requests.codes.OK, content=content)
@httmock.urlmatch(netloc=r'localhost')
def post(url, request):
if request.method != 'POST':
return
LOG.debug("POST mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
if 'interfaces/GigabitEthernet' in url.path:
return {'status_code': requests.codes.NO_CONTENT}
if 'global/local-users' in url.path:
if 'username' not in request.body:
return {'status_code': requests.codes.BAD_REQUEST}
if '"privilege": 20' in request.body:
return {'status_code': requests.codes.BAD_REQUEST}
headers = {'location': '%s/test-user' % url.geturl()}
return httmock.response(requests.codes.CREATED, headers=headers)
if 'vpn-svc/ike/policies' in url.path:
headers = {'location': "%s/2" % url.geturl()}
return httmock.response(requests.codes.CREATED, headers=headers)
if 'vpn-svc/ipsec/policies' in url.path:
m = re.search(r'"policy-id": "(\S+)"', request.body)
if m:
headers = {'location': "%s/%s" % (url.geturl(), m.group(1))}
return httmock.response(requests.codes.CREATED, headers=headers)
return {'status_code': requests.codes.BAD_REQUEST}
if 'vpn-svc/ike/keyrings' in url.path:
headers = {'location': "%s/5" % url.geturl()}
return httmock.response(requests.codes.CREATED, headers=headers)
if 'vpn-svc/site-to-site' in url.path:
m = re.search(r'"vpn-interface-name": "(\S+)"', request.body)
if m:
headers = {'location': "%s/%s" % (url.geturl(), m.group(1))}
return httmock.response(requests.codes.CREATED, headers=headers)
return {'status_code': requests.codes.BAD_REQUEST}
if 'routing-svc/static-routes' in url.path:
headers = {'location':
"%s/10.1.0.0_24_GigabitEthernet1" % url.geturl()}
return httmock.response(requests.codes.CREATED, headers=headers)
@filter_request(['post'], 'global/local-users')
@httmock.urlmatch(netloc=r'localhost')
def post_change_attempt(url, request):
LOG.debug("POST change value mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.NOT_FOUND,
'content': {
u'error-code': -1,
u'error-message': u'user test-user already exists'}}
@httmock.urlmatch(netloc=r'localhost')
def post_duplicate(url, request):
LOG.debug("POST duplicate mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST,
'content': {
u'error-code': -1,
u'error-message': u'policy 2 exist, not allow to '
u'update policy using POST method'}}
@filter_request(['post'], 'vpn-svc/site-to-site')
@httmock.urlmatch(netloc=r'localhost')
def post_missing_ipsec_policy(url, request):
LOG.debug("POST missing ipsec policy mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST}
@filter_request(['post'], 'vpn-svc/site-to-site')
@httmock.urlmatch(netloc=r'localhost')
def post_missing_ike_policy(url, request):
LOG.debug("POST missing ike policy mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST}
@filter_request(['post'], 'vpn-svc/site-to-site')
@httmock.urlmatch(netloc=r'localhost')
def post_bad_ip(url, request):
LOG.debug("POST bad IP mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST}
@filter_request(['post'], 'vpn-svc/site-to-site')
@httmock.urlmatch(netloc=r'localhost')
def post_bad_mtu(url, request):
LOG.debug("POST bad mtu mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST}
@filter_request(['post'], 'vpn-svc/ipsec/policies')
@httmock.urlmatch(netloc=r'localhost')
def post_bad_lifetime(url, request):
LOG.debug("POST bad lifetime mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST}
@filter_request(['post'], 'vpn-svc/ipsec/policies')
@httmock.urlmatch(netloc=r'localhost')
def post_bad_name(url, request):
LOG.debug("POST bad IPSec policy name for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
return {'status_code': requests.codes.BAD_REQUEST}
@httmock.urlmatch(netloc=r'localhost')
def put(url, request):
if request.method != 'PUT':
return
LOG.debug("PUT mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
# Any resource
return {'status_code': requests.codes.NO_CONTENT}
@httmock.urlmatch(netloc=r'localhost')
def delete(url, request):
if request.method != 'DELETE':
return
LOG.debug("DELETE mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
# Any resource
return {'status_code': requests.codes.NO_CONTENT}
@httmock.urlmatch(netloc=r'localhost')
def delete_unknown(url, request):
if request.method != 'DELETE':
return
LOG.debug("DELETE unknown mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
# Any resource
return {'status_code': requests.codes.NOT_FOUND,
'content': {
u'error-code': -1,
u'error-message': 'user unknown not found'}}
@httmock.urlmatch(netloc=r'localhost')
def delete_not_allowed(url, request):
if request.method != 'DELETE':
return
LOG.debug("DELETE not allowed mock for %s", url)
if not request.headers.get('X-auth-token', None):
return {'status_code': requests.codes.UNAUTHORIZED}
# Any resource
return {'status_code': requests.codes.METHOD_NOT_ALLOWED}

File diff suppressed because it is too large Load Diff

View File

@ -14,6 +14,7 @@
import copy import copy
import httplib import httplib
import operator
import mock import mock
@ -124,7 +125,7 @@ class TestCiscoCsrIPSecConnection(base.BaseTestCase):
steps are called in reverse order. At the end, there should be no steps are called in reverse order. At the end, there should be no
rollback infromation for the connection. rollback infromation for the connection.
""" """
def fake_route_check_fails(*args, **kwargs): def fake_route_check_fails(*args):
if args[0] == 'Static Route': if args[0] == 'Static Route':
# So that subsequent calls to CSR rest client (for rollback) # So that subsequent calls to CSR rest client (for rollback)
# will fake as passing. # will fake as passing.
@ -1530,7 +1531,8 @@ class TestCiscoCsrIPsecDeviceDriverSyncStatuses(base.BaseTestCase):
u'4': {u'status': constants.ACTIVE, u'4': {u'status': constants.ACTIVE,
u'updated_pending_status': True}} u'updated_pending_status': True}}
}] }]
self.assertEqual(expected_report, report) self.assertEqual(expected_report,
sorted(report, key=operator.itemgetter('id')))
# Check that service and connection statuses are updated # Check that service and connection statuses are updated
self.assertEqual(constants.ACTIVE, vpn_service1.last_status) self.assertEqual(constants.ACTIVE, vpn_service1.last_status)
self.assertEqual(constants.ACTIVE, self.assertEqual(constants.ACTIVE,

View File

@ -1,14 +0,0 @@
# Copyright 2013, Nachi Ueno, NTT I3, Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.

View File

@ -29,19 +29,15 @@ from neutron.tests.unit import testlib_api
_uuid = uuidutils.generate_uuid _uuid = uuidutils.generate_uuid
FAKE_VPN_CONN_ID = _uuid() FAKE_VPN_CONN_ID = _uuid()
FAKE_SERVICE_ID = _uuid()
FAKE_VPN_CONNECTION = { FAKE_VPN_CONNECTION = {
'vpnservice_id': _uuid(), 'vpnservice_id': FAKE_SERVICE_ID,
'id': FAKE_VPN_CONN_ID, 'id': FAKE_VPN_CONN_ID,
'ikepolicy_id': _uuid(), 'ikepolicy_id': _uuid(),
'ipsecpolicy_id': _uuid(), 'ipsecpolicy_id': _uuid(),
'tenant_id': _uuid() 'tenant_id': _uuid()
} }
FAKE_SERVICE_ID = _uuid()
FAKE_VPN_CONNECTION = {
'vpnservice_id': FAKE_SERVICE_ID
}
FAKE_ROUTER_ID = _uuid() FAKE_ROUTER_ID = _uuid()
FAKE_VPN_SERVICE = { FAKE_VPN_SERVICE = {
'router_id': FAKE_ROUTER_ID 'router_id': FAKE_ROUTER_ID

View File

@ -93,8 +93,9 @@ class TestVPNAgent(base.BaseTestCase):
def test_get_namespace(self): def test_get_namespace(self):
router_id = _uuid() router_id = _uuid()
ns = "ns-" + router_id
ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, ri = l3_agent.RouterInfo(router_id, self.conf.root_helper,
self.conf.use_namespaces, {}) self.conf.use_namespaces, {}, ns_name=ns)
self.agent.router_info = {router_id: ri} self.agent.router_info = {router_id: ri}
namespace = self.agent.get_namespace(router_id) namespace = self.agent.get_namespace(router_id)
self.assertTrue(namespace.endswith(router_id)) self.assertTrue(namespace.endswith(router_id))
@ -170,9 +171,10 @@ class TestVPNAgent(base.BaseTestCase):
'neutron.agent.linux.iptables_manager.IptablesManager').start() 'neutron.agent.linux.iptables_manager.IptablesManager').start()
router_id = _uuid() router_id = _uuid()
ri = l3_agent.RouterInfo(router_id, self.conf.root_helper, ri = l3_agent.RouterInfo(router_id, self.conf.root_helper,
self.conf.use_namespaces, {}) self.conf.use_namespaces, {},
ns_name="qrouter-%s" % router_id)
ri.router = { ri.router = {
'id': _uuid(), 'id': router_id,
'admin_state_up': True, 'admin_state_up': True,
'routes': [], 'routes': [],
'external_gateway_info': {}, 'external_gateway_info': {},
@ -183,15 +185,14 @@ class TestVPNAgent(base.BaseTestCase):
self.agent._router_removed(router_id) self.agent._router_removed(router_id)
device.destroy_router.assert_called_once_with(router_id) device.destroy_router.assert_called_once_with(router_id)
def test_process_routers(self): def test_process_router_if_compatible(self):
self.plugin_api.get_external_network_id.return_value = None self.plugin_api.get_external_network_id.return_value = None
routers = [ router = {'id': _uuid(),
{'id': _uuid(), 'admin_state_up': True,
'admin_state_up': True, 'routes': [],
'routes': [], 'external_gateway_info': {}}
'external_gateway_info': {}}]
device = mock.Mock() device = mock.Mock()
self.agent.devices = [device] self.agent.devices = [device]
self.agent._process_routers(routers, False) self.agent._process_router_if_compatible(router)
device.sync.assert_called_once_with(mock.ANY, routers) device.sync.assert_called_once_with(mock.ANY, [router])

View File

@ -25,13 +25,11 @@ module=periodic_task
module=policy module=policy
module=processutils module=processutils
module=service module=service
module=sslutils
module=strutils module=strutils
module=systemd module=systemd
module=threadgroup module=threadgroup
module=timeutils module=timeutils
module=uuidutils module=uuidutils
module=versionutils
# The base module to hold the copy of openstack.common # The base module to hold the copy of openstack.common
base=neutron base=neutron

View File

@ -9,26 +9,28 @@ Routes>=1.12.3,!=2.0
anyjson>=0.3.3 anyjson>=0.3.3
argparse argparse
Babel>=1.3 Babel>=1.3
eventlet>=0.15.1 eventlet>=0.15.2
greenlet>=0.3.2 greenlet>=0.3.2
httplib2>=0.7.5 httplib2>=0.7.5
requests>=1.2.1,!=2.4.0 requests>=2.2.0,!=2.4.0
iso8601>=0.1.9 iso8601>=0.1.9
jsonrpclib jsonrpclib
Jinja2 Jinja2
keystonemiddleware>=1.0.0 keystonemiddleware>=1.0.0
kombu>=2.4.8
netaddr>=0.7.12 netaddr>=0.7.12
python-neutronclient>=2.3.6,<3 python-neutronclient>=2.3.6,<3
SQLAlchemy>=0.8.4,<=0.8.99,>=0.9.7,<=0.9.99 SQLAlchemy>=0.8.4,<=0.8.99,>=0.9.7,<=0.9.99
WebOb>=1.2.3 WebOb>=1.2.3
python-keystoneclient>=0.10.0 python-keystoneclient>=0.11.1
alembic>=0.6.4 alembic>=0.6.4
six>=1.7.0 six>=1.7.0
stevedore>=0.14 stevedore>=1.0.0 # Apache-2.0
oslo.config>=1.4.0.0a3 oslo.config>=1.4.0 # Apache-2.0
oslo.db>=0.4.0 # Apache-2.0 oslo.db>=1.0.0 # Apache-2.0
oslo.messaging>=1.4.0.0a3 oslo.i18n>=1.0.0 # Apache-2.0
oslo.rootwrap>=1.3.0.0a1 oslo.messaging>=1.4.0
oslo.rootwrap>=1.3.0
oslo.serialization>=1.0.0 # Apache-2.0
oslo.utils>=1.0.0 # Apache-2.0
python-novaclient>=2.18.0 python-novaclient>=2.18.0

View File

@ -1,6 +1,6 @@
[metadata] [metadata]
name = neutron name = neutron
version = 2014.2 version = 2015.1
summary = OpenStack Networking summary = OpenStack Networking
description-file = description-file =
README.rst README.rst
@ -55,6 +55,7 @@ data_files =
etc/neutron/plugins/bigswitch/ssl/host_certs/README etc/neutron/plugins/bigswitch/ssl/host_certs/README
etc/neutron/plugins/brocade = etc/neutron/plugins/brocade/brocade.ini etc/neutron/plugins/brocade = etc/neutron/plugins/brocade/brocade.ini
etc/neutron/plugins/cisco = etc/neutron/plugins/cisco =
etc/neutron/plugins/cisco/cisco_cfg_agent.ini
etc/neutron/plugins/cisco/cisco_plugins.ini etc/neutron/plugins/cisco/cisco_plugins.ini
etc/neutron/plugins/cisco/cisco_router_plugin.ini etc/neutron/plugins/cisco/cisco_router_plugin.ini
etc/neutron/plugins/cisco/cisco_vpn_agent.ini etc/neutron/plugins/cisco/cisco_vpn_agent.ini
@ -133,14 +134,13 @@ neutron.core_plugins =
embrane = neutron.plugins.embrane.plugins.embrane_ml2_plugin:EmbraneMl2Plugin embrane = neutron.plugins.embrane.plugins.embrane_ml2_plugin:EmbraneMl2Plugin
hyperv = neutron.plugins.hyperv.hyperv_neutron_plugin:HyperVNeutronPlugin hyperv = neutron.plugins.hyperv.hyperv_neutron_plugin:HyperVNeutronPlugin
ibm = neutron.plugins.ibm.sdnve_neutron_plugin:SdnvePluginV2 ibm = neutron.plugins.ibm.sdnve_neutron_plugin:SdnvePluginV2
linuxbridge = neutron.plugins.linuxbridge.lb_neutron_plugin:LinuxBridgePluginV2
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2 midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
mlnx = neutron.plugins.mlnx.mlnx_plugin:MellanoxEswitchPlugin mlnx = neutron.plugins.mlnx.mlnx_plugin:MellanoxEswitchPlugin
nec = neutron.plugins.nec.nec_plugin:NECPluginV2 nec = neutron.plugins.nec.nec_plugin:NECPluginV2
nuage = neutron.plugins.nuage.plugin:NuagePlugin nuage = neutron.plugins.nuage.plugin:NuagePlugin
metaplugin = neutron.plugins.metaplugin.meta_neutron_plugin:MetaPluginV2 metaplugin = neutron.plugins.metaplugin.meta_neutron_plugin:MetaPluginV2
oneconvergence = neutron.plugins.oneconvergence.plugin.OneConvergencePluginV2 oneconvergence = neutron.plugins.oneconvergence.plugin:OneConvergencePluginV2
openvswitch = neutron.plugins.openvswitch.ovs_neutron_plugin:OVSNeutronPluginV2 openvswitch = neutron.plugins.openvswitch.ovs_neutron_plugin:OVSNeutronPluginV2
plumgrid = neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin:NeutronPluginPLUMgridV2 plumgrid = neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin:NeutronPluginPLUMgridV2
ryu = neutron.plugins.ryu.ryu_neutron_plugin:RyuNeutronPluginV2 ryu = neutron.plugins.ryu.ryu_neutron_plugin:RyuNeutronPluginV2

View File

@ -3,7 +3,7 @@
# process, which may cause wedges in the gate later. # process, which may cause wedges in the gate later.
hacking>=0.9.2,<0.10 hacking>=0.9.2,<0.10
cliff>=1.6.0 cliff>=1.7.0 # Apache-2.0
coverage>=3.6 coverage>=3.6
discover discover
fixtures>=0.3.14 fixtures>=0.3.14
@ -11,8 +11,12 @@ mock>=1.0
python-subunit>=0.0.18 python-subunit>=0.0.18
ordereddict ordereddict
requests-mock>=0.4.0 # Apache-2.0 requests-mock>=0.4.0 # Apache-2.0
sphinx>=1.1.2,!=1.2.0,<1.3 sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
oslosphinx>=2.2.0.0a2 oslosphinx>=2.2.0 # Apache-2.0
testrepository>=0.0.18 testrepository>=0.0.18
testtools>=0.9.34 testtools>=0.9.34
testscenarios>=0.4
WebTest>=2.0 WebTest>=2.0
oslotest>=1.1.0 # Apache-2.0
psycopg2
MySQL-python

13
tox.ini
View File

@ -1,5 +1,5 @@
[tox] [tox]
envlist = py26,py27,py33,pep8 envlist = py26,py27,py33,py34,pep8
minversion = 1.6 minversion = 1.6
skipsdist = True skipsdist = True
@ -64,13 +64,11 @@ commands = python setup.py build_sphinx
# E126 continuation line over-indented for hanging indent # E126 continuation line over-indented for hanging indent
# E128 continuation line under-indented for visual indent # E128 continuation line under-indented for visual indent
# E129 visually indented line with same indent as next logical line # E129 visually indented line with same indent as next logical line
# E251 unexpected spaces around keyword / parameter equals
# E265 block comment should start with # # E265 block comment should start with #
# E713 test for membership should be not in # E713 test for membership should be not in
# F402 import module shadowed by loop variable # F402 import module shadowed by loop variable
# F811 redefinition of unused variable # F811 redefinition of unused variable
# F812 list comprehension redefines name from line # F812 list comprehension redefines name from line
# H104 file contains nothing but comments
# H237 module is removed in Python 3 # H237 module is removed in Python 3
# H305 imports not grouped correctly # H305 imports not grouped correctly
# H307 like imports should be grouped together # H307 like imports should be grouped together
@ -79,11 +77,18 @@ commands = python setup.py build_sphinx
# H405 multi line docstring summary not separated with an empty line # H405 multi line docstring summary not separated with an empty line
# H904 Wrap long lines in parentheses instead of a backslash # H904 Wrap long lines in parentheses instead of a backslash
# TODO(marun) H404 multi line docstring should start with a summary # TODO(marun) H404 multi line docstring should start with a summary
ignore = E125,E126,E128,E129,E251,E265,E713,F402,F811,F812,H104,H237,H305,H307,H401,H402,H404,H405,H904 ignore = E125,E126,E128,E129,E265,E713,F402,F811,F812,H237,H305,H307,H401,H402,H404,H405,H904
show-source = true show-source = true
builtins = _ builtins = _
exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,.ropeproject,rally-scenarios exclude = .venv,.git,.tox,dist,doc,*openstack/common*,*lib/python*,*egg,build,tools,.ropeproject,rally-scenarios
[testenv:pylint]
deps =
{[testenv]deps}
pylint
commands =
pylint --rcfile=.pylintrc --output-format=colorized {posargs:neutron}
[hacking] [hacking]
import_exceptions = neutron.openstack.common.gettextutils import_exceptions = neutron.openstack.common.gettextutils
local-check-factory = neutron.hacking.checks.factory local-check-factory = neutron.hacking.checks.factory