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]
# Add <file or directory> to the black list. It should be a base name, not a
# 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]
# NOTE(justinsb): We might want to have a 2nd strict pylintrc in future
# C0111: Don't require docstrings on every method
# W0511: TODOs in code comments are fine.
# W0142: *args and **kwargs are fine.
# W0622: Redefining id is fine.
disable=C0111,W0511,W0142,W0622
[MESSAGES CONTROL]
# NOTE(gus): This is a long list. A number of these are important and
# should be re-enabled once the offending code is fixed (or marked
# with a local disable)
disable=
# "F" Fatal errors that prevent further processing
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-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
# 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-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.
no-docstring-rgx=((__.*__)|([tT]est.*)|setUp|tearDown)$
[Design]
max-public-methods=100
min-public-methods=0
max-args=6
[Variables]
[FORMAT]
# Maximum number of characters on a single line.
max-line-length=79
[VARIABLES]
# List of additional names supposed to be defined in builtins. Remember that
# you should avoid to define new builtins when possible.
# _ is used by our localization
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
- [N322] We do not use @authors tags in source files. We have git to track
authorship.
- [N323] assert_called_once() is not a valid method
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 import manager
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 uuidutils
from neutron.plugins.common import constants
@ -601,6 +602,16 @@ class VPNPluginDb(vpnaas.VPNPluginBase, base_db.CommonDbMixin):
router_id=router_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():
def _get_agent_hosting_vpn_services(self, context, host):
@ -646,7 +657,7 @@ class VPNPluginRpcDbMixin():
vpnservice_db = self._get_vpnservice(
context, vpnservice['id'])
except vpnaas.VPNServiceNotFound:
LOG.warn(_('vpnservice %s in db is already deleted'),
LOG.warn(_LW('vpnservice %s in db is already deleted'),
vpnservice['id'])
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:
device.destroy_router(router_id)
def _process_routers(self, routers, all_routers=False):
def _process_router_if_compatible(self, router):
"""Router sync event.
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:
device.sync(self.context, routers)
device.sync(self.context, [router])
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 neutron.openstack.common import jsonutils
from neutron.openstack.common.gettextutils import _LE, _LW
from neutron.openstack.common import log as logging
@ -84,7 +85,7 @@ class CsrRestClient(object):
and 'detail' fields).
"""
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()
if method == 'POST' and self.status == requests.codes.CREATED:
return response.headers.get('location', '')
@ -97,21 +98,21 @@ class CsrRestClient(object):
def _request(self, method, url, **kwargs):
"""Perform REST request and save response info."""
try:
LOG.debug(_("%(method)s: Request for %(resource)s payload: "
"%(payload)s"),
LOG.debug("%(method)s: Request for %(resource)s payload: "
"%(payload)s",
{'method': method.upper(), 'resource': url,
'payload': kwargs.get('data')})
start_time = time.time()
response = self.session.request(method, url, verify=False,
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(),
'time': time.time() - start_time})
except (r_exc.Timeout, r_exc.SSLError) as te:
# Should never see SSLError, unless requests package is old (<2.0)
timeout_val = 0.0 if self.timeout is None else self.timeout
LOG.warning(_("%(method)s: Request timeout%(ssl)s "
"(%(timeout).3f sec) for CSR(%(host)s)"),
LOG.warning(_LW("%(method)s: Request timeout%(ssl)s "
"(%(timeout).3f sec) for CSR(%(host)s)"),
{'method': method,
'timeout': timeout_val,
'ssl': '(SSLError)'
@ -119,17 +120,18 @@ class CsrRestClient(object):
'host': self.host})
self.status = requests.codes.REQUEST_TIMEOUT
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})
self.status = requests.codes.NOT_FOUND
except Exception as e:
LOG.error(_("%(method)s: Unexpected error for CSR (%(host)s): "
"%(error)s"),
LOG.error(_LE("%(method)s: Unexpected error for CSR (%(host)s): "
"%(error)s"),
{'method': method, 'host': self.host, 'error': e})
self.status = requests.codes.INTERNAL_SERVER_ERROR
else:
self.status = response.status_code
LOG.debug(_("%(method)s: Completed [%(status)s]"),
LOG.debug("%(method)s: Completed [%(status)s]",
{'method': method, 'status': self.status})
return self._response_info_for(response, method)
@ -144,16 +146,16 @@ class CsrRestClient(object):
headers = {'Content-Length': '0',
'Accept': 'application/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
else 'Reauthenticating', 'host': self.host})
self.token = None
response = self._request("POST", url, headers=headers, auth=self.auth)
if response:
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
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})
def _do_request(self, method, resource, payload=None, more_headers=None,
@ -188,7 +190,7 @@ class CsrRestClient(object):
headers=headers)
if self.status != requests.codes.REQUEST_TIMEOUT:
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})
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 rpc as n_rpc
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 log as logging
from neutron.openstack.common import loopingcall
@ -125,7 +126,7 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
def vpnservice_updated(self, context, **kwargs):
"""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', ''))
self.sync(context, [])
@ -147,20 +148,20 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
ipsec_conn = vpn_service.conn_state[conn_id]
config_changed = ipsec_conn.check_for_changes(conn_data)
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.create_ipsec_site_connection(context, conn_data)
ipsec_conn.conn_info = conn_data
if ipsec_conn.forced_down:
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)
ipsec_conn.set_admin_state(is_up=True)
ipsec_conn.forced_down = False
else:
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)
ipsec_conn.set_admin_state(is_up=False)
ipsec_conn.forced_down = True
@ -168,12 +169,12 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
ipsec_conn = vpn_service.create_connection(conn_data)
ipsec_conn.create_ipsec_site_connection(context, conn_data)
if not vpn_service.is_admin_up or not conn_is_admin_up:
LOG.debug(_("Update: Created new connection %s in admin down "
"state"), conn_id)
LOG.debug("Update: Created new connection %s in admin down "
"state", conn_id)
ipsec_conn.set_admin_state(is_up=False)
ipsec_conn.forced_down = True
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.last_status = conn_data['status']
@ -184,11 +185,11 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
"""Handle notification for a single VPN Service and its connections."""
vpn_service_id = service_data['id']
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 = self.service_state[vpn_service_id]
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)
if not vpn_service:
return
@ -199,7 +200,7 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
vpn_service.is_admin_up = service_data[u'admin_state_up']
for conn_data in service_data['ipsec_conns']:
self.update_connection(context, vpn_service_id, conn_data)
LOG.debug(_("Update: Completed update processing"))
LOG.debug("Update: Completed update processing")
return vpn_service
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:
service_state.conn_state[conn_id].is_dirty = True
connection_count += 1
LOG.debug(_("Mark: %(service)d VPN services and %(conn)d IPSec "
"connections marked dirty"), {'service': service_count,
'conn': connection_count})
LOG.debug("Mark: %(service)d VPN services and %(conn)d IPSec "
"connections marked dirty", {'service': service_count,
'conn': connection_count})
def remove_unknown_connections(self, context):
"""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]
elif dirty:
self.connections_removed = True
LOG.debug(_("Sweep: Removed %(service)d dirty VPN service%(splural)s "
"and %(conn)d dirty IPSec connection%(cplural)s"),
LOG.debug("Sweep: Removed %(service)d dirty VPN service%(splural)s "
"and %(conn)d dirty IPSec connection%(cplural)s",
{'service': service_count, 'conn': connection_count,
'splural': 's'[service_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
data is returned.
"""
LOG.debug(_("Report: Collecting status for IPSec connections on VPN "
"service %s"), vpn_service.service_id)
LOG.debug("Report: Collecting status for IPSec connections on VPN "
"service %s", vpn_service.service_id)
tunnels = vpn_service.get_ipsec_connections_status()
report = {}
for connection in vpn_service.conn_state.values():
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
else:
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,
'status': current_status})
frag = connection.update_status_and_build_report(current_status)
if frag:
LOG.debug(_("Report: Adding info for IPSec connection %s"),
LOG.debug("Report: Adding info for IPSec connection %s",
connection.conn_id)
report.update(frag)
return report
@ -301,7 +302,7 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
pending_handled = plugin_utils.in_pending_status(
vpn_service.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)
return {u'id': vpn_service.service_id,
u'status': vpn_service.last_status,
@ -323,17 +324,17 @@ class CiscoCsrIPsecDriver(device_drivers.DeviceDriver):
def report_status_internal(self, context):
"""Generate report and send to plugin, if anything changed."""
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():
LOG.debug(_("Report: Collecting status for VPN service %s"),
LOG.debug("Report: Collecting status for VPN service %s",
vpn_service_id)
report = self.build_report_for_service(vpn_service)
if report:
service_report.append(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)
LOG.debug(_("Report: Completed status report processing"))
LOG.debug("Report: Completed status report processing")
return service_report
@lockutils.synchronized('vpn-agent', 'neutron-')
@ -617,8 +618,8 @@ class CiscoCsrIPSecConnection(object):
LOG.debug("%(resource)s %(which)s is configured",
{'resource': resource, 'which': which})
return
LOG.error(_("Unable to create %(resource)s %(which)s: "
"%(status)d"),
LOG.error(_LE("Unable to create %(resource)s %(which)s: "
"%(status)d"),
{'resource': resource, 'which': which,
'status': self.csr.status})
# ToDO(pcm): Set state to error
@ -630,7 +631,7 @@ class CiscoCsrIPSecConnection(object):
try:
getattr(self.csr, create_action)(info)
except AttributeError:
LOG.exception(_("Internal error - '%s' is not defined"),
LOG.exception(_LE("Internal error - '%s' is not defined"),
create_action)
raise CsrResourceCreateFailure(resource=title,
which=resource_id)
@ -643,22 +644,22 @@ class CiscoCsrIPSecConnection(object):
LOG.debug("%(resource)s configuration %(which)s was removed",
{'resource': resource, 'which': which})
else:
LOG.warning(_("Unable to delete %(resource)s %(which)s: "
"%(status)d"), {'resource': resource,
'which': which,
'status': status})
LOG.warning(_LW("Unable to delete %(resource)s %(which)s: "
"%(status)d"), {'resource': resource,
'which': which,
'status': status})
def do_rollback(self):
"""Undo create steps that were completed successfully."""
for step in reversed(self.steps):
delete_action = 'delete_%s' % step.action
LOG.debug(_("Performing rollback action %(action)s for "
"resource %(resource)s"), {'action': delete_action,
'resource': step.title})
LOG.debug("Performing rollback action %(action)s for "
"resource %(resource)s", {'action': delete_action,
'resource': step.title})
try:
getattr(self.csr, delete_action)(step.resource_id)
except AttributeError:
LOG.exception(_("Internal error - '%s' is not defined"),
LOG.exception(_LE("Internal error - '%s' is not defined"),
delete_action)
raise CsrResourceCreateFailure(resource=step.title,
which=step.resource_id)
@ -678,7 +679,7 @@ class CiscoCsrIPSecConnection(object):
ike_policy_id = conn_info['cisco']['ike_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
try:
psk_info = self.create_psk_info(psk_id, conn_info)
@ -711,10 +712,10 @@ class CiscoCsrIPSecConnection(object):
route_id, 'Static Route')
except CsrResourceCreateFailure:
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)
else:
LOG.info(_("SUCCESS: Created IPSec site-to-site connection %s"),
LOG.info(_LI("SUCCESS: Created IPSec site-to-site connection %s"),
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
failures.
"""
LOG.debug(_('Deleting IPSec connection %s'), conn_id)
LOG.debug('Deleting IPSec connection %s', conn_id)
if not self.steps:
LOG.warning(_('Unable to find connection %s'), conn_id)
LOG.warning(_LW('Unable to find connection %s'), conn_id)
else:
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)
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)
if self.csr.status != requests.codes.NO_CONTENT:
state = "UP" if is_up else "DOWN"
LOG.error(_("Unable to change %(tunnel)s admin state to "
"%(state)s"), {'tunnel': self.tunnel, 'state': state})
LOG.error(_LE("Unable to change %(tunnel)s admin state to "
"%(state)s"), {'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.common import rpc as n_rpc
from neutron import context
from neutron.openstack.common.gettextutils import _LE
from neutron.openstack.common import lockutils
from neutron.openstack.common import log as logging
from neutron.openstack.common import loopingcall
@ -244,7 +245,7 @@ class BaseSwanProcess():
self.start()
except RuntimeError:
LOG.exception(
_("Failed to enable vpn process on router %s"),
_LE("Failed to enable vpn process on router %s"),
self.id)
def disable(self):
@ -255,7 +256,7 @@ class BaseSwanProcess():
self.remove_config()
except RuntimeError:
LOG.exception(
_("Failed to disable vpn process on router %s"),
_LE("Failed to disable vpn process on router %s"),
self.id)
@abc.abstractmethod

View File

@ -15,6 +15,7 @@
# under the License.
from neutron.db.vpn import vpn_db
from neutron.openstack.common.gettextutils import _LI
from neutron.openstack.common import log as logging
from neutron.plugins.common import constants
from neutron.services import service_base
@ -41,7 +42,7 @@ class VPNDriverPlugin(VPNPlugin, vpn_db.VPNPluginRpcDbMixin):
# Load the service driver from neutron.conf.
drivers, default_provider = service_base.load_drivers(
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]
def _get_driver_for_vpnservice(self, vpnservice):

View File

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

View File

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

View File

@ -20,6 +20,7 @@ from neutron.common import exceptions
from neutron.db import model_base
from neutron.db import models_v2
from neutron.db.vpn import vpn_db
from neutron.openstack.common.gettextutils import _LI
from neutron.openstack.common import log as logging
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.
"""
csr_id = get_next_available_id(session, map_policy_field, policy_type)
LOG.debug(_("Reserved new CSR ID %(csr_id)d for %(policy)s "
"ID %(policy_id)s"), {'csr_id': csr_id,
'policy': policy_type,
'policy_id': policy_id})
LOG.debug("Reserved new CSR ID %(csr_id)d for %(policy)s "
"ID %(policy_id)s", {'csr_id': csr_id,
'policy': policy_type,
'policy_id': policy_id})
return csr_id
@ -183,9 +184,9 @@ def get_tunnel_mapping_for(conn_id, session):
try:
entry = session.query(IdentifierMap).filter_by(
ipsec_site_conn_id=conn_id).one()
LOG.debug(_("Mappings for IPSec connection %(conn)s - "
"tunnel=%(tunnel)s ike_policy=%(csr_ike)d "
"ipsec_policy=%(csr_ipsec)d"),
LOG.debug("Mappings for IPSec connection %(conn)s - "
"tunnel=%(tunnel)s ike_policy=%(csr_ike)d "
"ipsec_policy=%(csr_ipsec)d",
{'conn': conn_id, 'tunnel': entry.csr_tunnel_id,
'csr_ike': entry.csr_ike_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 "
"mapping table for connection %s") % conn_id
raise CsrInternalError(reason=msg)
LOG.info(_("Mapped connection %(conn_id)s to Tunnel%(tunnel_id)d "
"using IKE policy ID %(ike_id)d and IPSec policy "
"ID %(ipsec_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 "
"ID %(ipsec_id)d"),
{'conn_id': conn_id, 'tunnel_id': csr_tunnel_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():
sess_qry = context.session.query(IdentifierMap)
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
# can't set state of resource to error.
return
LOG.debug(_('Notify agent at %(topic)s.%(host)s the message '
'%(method)s %(args)s for router %(router)s'),
LOG.debug('Notify agent at %(topic)s.%(host)s the message '
'%(method)s %(args)s for router %(router)s',
{'topic': self.topic,
'host': host,
'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
)
self._subnet_id = uuidutils.generate_uuid()
self.core_plugin = TestVpnCorePlugin
self.core_plugin = TestVpnCorePlugin()
self.plugin = vpn_plugin.VPNPlugin()
ext_mgr = api_extensions.PluginAwareExtensionManager(
extensions_path,
@ -867,6 +867,55 @@ class TestVpnaas(VPNPluginDbTestCase):
if k in 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):
"""Test case to update a vpnservice."""
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 httplib
import operator
import mock
@ -124,7 +125,7 @@ class TestCiscoCsrIPSecConnection(base.BaseTestCase):
steps are called in reverse order. At the end, there should be no
rollback infromation for the connection.
"""
def fake_route_check_fails(*args, **kwargs):
def fake_route_check_fails(*args):
if args[0] == 'Static Route':
# So that subsequent calls to CSR rest client (for rollback)
# will fake as passing.
@ -1530,7 +1531,8 @@ class TestCiscoCsrIPsecDeviceDriverSyncStatuses(base.BaseTestCase):
u'4': {u'status': constants.ACTIVE,
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
self.assertEqual(constants.ACTIVE, vpn_service1.last_status)
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
FAKE_VPN_CONN_ID = _uuid()
FAKE_SERVICE_ID = _uuid()
FAKE_VPN_CONNECTION = {
'vpnservice_id': _uuid(),
'vpnservice_id': FAKE_SERVICE_ID,
'id': FAKE_VPN_CONN_ID,
'ikepolicy_id': _uuid(),
'ipsecpolicy_id': _uuid(),
'tenant_id': _uuid()
}
FAKE_SERVICE_ID = _uuid()
FAKE_VPN_CONNECTION = {
'vpnservice_id': FAKE_SERVICE_ID
}
FAKE_ROUTER_ID = _uuid()
FAKE_VPN_SERVICE = {
'router_id': FAKE_ROUTER_ID

View File

@ -93,8 +93,9 @@ class TestVPNAgent(base.BaseTestCase):
def test_get_namespace(self):
router_id = _uuid()
ns = "ns-" + router_id
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}
namespace = self.agent.get_namespace(router_id)
self.assertTrue(namespace.endswith(router_id))
@ -170,9 +171,10 @@ class TestVPNAgent(base.BaseTestCase):
'neutron.agent.linux.iptables_manager.IptablesManager').start()
router_id = _uuid()
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 = {
'id': _uuid(),
'id': router_id,
'admin_state_up': True,
'routes': [],
'external_gateway_info': {},
@ -183,15 +185,14 @@ class TestVPNAgent(base.BaseTestCase):
self.agent._router_removed(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
routers = [
{'id': _uuid(),
'admin_state_up': True,
'routes': [],
'external_gateway_info': {}}]
router = {'id': _uuid(),
'admin_state_up': True,
'routes': [],
'external_gateway_info': {}}
device = mock.Mock()
self.agent.devices = [device]
self.agent._process_routers(routers, False)
device.sync.assert_called_once_with(mock.ANY, routers)
self.agent._process_router_if_compatible(router)
device.sync.assert_called_once_with(mock.ANY, [router])

View File

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

View File

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

View File

@ -1,6 +1,6 @@
[metadata]
name = neutron
version = 2014.2
version = 2015.1
summary = OpenStack Networking
description-file =
README.rst
@ -55,6 +55,7 @@ data_files =
etc/neutron/plugins/bigswitch/ssl/host_certs/README
etc/neutron/plugins/brocade = etc/neutron/plugins/brocade/brocade.ini
etc/neutron/plugins/cisco =
etc/neutron/plugins/cisco/cisco_cfg_agent.ini
etc/neutron/plugins/cisco/cisco_plugins.ini
etc/neutron/plugins/cisco/cisco_router_plugin.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
hyperv = neutron.plugins.hyperv.hyperv_neutron_plugin:HyperVNeutronPlugin
ibm = neutron.plugins.ibm.sdnve_neutron_plugin:SdnvePluginV2
linuxbridge = neutron.plugins.linuxbridge.lb_neutron_plugin:LinuxBridgePluginV2
midonet = neutron.plugins.midonet.plugin:MidonetPluginV2
ml2 = neutron.plugins.ml2.plugin:Ml2Plugin
mlnx = neutron.plugins.mlnx.mlnx_plugin:MellanoxEswitchPlugin
nec = neutron.plugins.nec.nec_plugin:NECPluginV2
nuage = neutron.plugins.nuage.plugin:NuagePlugin
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
plumgrid = neutron.plugins.plumgrid.plumgrid_plugin.plumgrid_plugin:NeutronPluginPLUMgridV2
ryu = neutron.plugins.ryu.ryu_neutron_plugin:RyuNeutronPluginV2

View File

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

13
tox.ini
View File

@ -1,5 +1,5 @@
[tox]
envlist = py26,py27,py33,pep8
envlist = py26,py27,py33,py34,pep8
minversion = 1.6
skipsdist = True
@ -64,13 +64,11 @@ commands = python setup.py build_sphinx
# E126 continuation line over-indented for hanging indent
# E128 continuation line under-indented for visual indent
# E129 visually indented line with same indent as next logical line
# E251 unexpected spaces around keyword / parameter equals
# E265 block comment should start with #
# E713 test for membership should be not in
# F402 import module shadowed by loop variable
# F811 redefinition of unused variable
# F812 list comprehension redefines name from line
# H104 file contains nothing but comments
# H237 module is removed in Python 3
# H305 imports not grouped correctly
# 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
# H904 Wrap long lines in parentheses instead of a backslash
# 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
builtins = _
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]
import_exceptions = neutron.openstack.common.gettextutils
local-check-factory = neutron.hacking.checks.factory