Initial commit

This commit is contained in:
Akihiro Motoki 2017-05-20 08:39:06 +09:00
commit 7fada8ebbf
36 changed files with 3820 additions and 0 deletions

2
.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*.pyc
*.swp

17
CONTRIBUTING.rst Normal file
View File

@ -0,0 +1,17 @@
If you would like to contribute to the development of OpenStack, you must
follow the steps in this page:
http://docs.openstack.org/infra/manual/developers.html
If you already have a good understanding of how the system works and your
OpenStack accounts are set up, you can skip to the development workflow
section of this documentation to learn how changes to OpenStack should be
submitted for review via the Gerrit tool:
http://docs.openstack.org/infra/manual/developers.html#development-workflow
Pull requests submitted through GitHub will be ignored.
Bugs should be filed on Launchpad, not GitHub:
https://bugs.launchpad.net/neutron-vpnaas-dashbaard

13
HACKING.rst Normal file
View File

@ -0,0 +1,13 @@
===========================================
Neutron VPNaaS Dashboard Style Commandments
===========================================
Read the OpenStack Style Commandments
http://docs.openstack.org/developer/hacking/
Project Specific Commandments
-----------------------------
- Read the Horizon contributing documentation at
http://docs.openstack.org/developer/horizon/contributing.html
- [M322] Method's default argument shouldn't be mutable.

176
LICENSE Normal file
View File

@ -0,0 +1,176 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.

9
README.rst Normal file
View File

@ -0,0 +1,9 @@
========================
Neutron VPNaaS Dashboard
========================
OpenStack Dashboard panels for Neutron VPNaaS
* Documentation: http://docs.openstack.org/developer/neutron-vpnaas-dashboard
* Source: http://git.openstack.org/cgit/openstack/neutron-vpnaas-dashboard
* Bugs: http://bugs.launchpad.net/neutron-vpnaas-dashboard

View File

@ -0,0 +1,381 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from __future__ import absolute_import
from collections import OrderedDict
from horizon.utils.memoized import memoized
from openstack_dashboard.api import neutron
from openstack_dashboard.contrib.developer.profiler import api as profiler
neutronclient = neutron.neutronclient
class IKEPolicy(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron VPN IKEPolicy."""
class IPSecPolicy(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron VPN IPSecPolicy."""
class IPSecSiteConnection(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron IPSecSiteConnection."""
class VPNService(neutron.NeutronAPIDictWrapper):
"""Wrapper for neutron VPNService."""
@profiler.trace
def vpnservice_create(request, **kwargs):
"""Create VPNService
:param request: request context
:param admin_state_up: admin state (default on)
:param name: name for VPNService
:param description: description for VPNService
:param router_id: router id for router of VPNService
:param subnet_id: subnet id for subnet of VPNService
"""
body = {'vpnservice':
{'admin_state_up': kwargs['admin_state_up'],
'name': kwargs['name'],
'description': kwargs['description'],
'router_id': kwargs['router_id'],
'subnet_id': kwargs['subnet_id']}
}
vpnservice = neutronclient(request).create_vpnservice(body).get(
'vpnservice')
return VPNService(vpnservice)
@profiler.trace
def vpnservice_list(request, **kwargs):
return _vpnservice_list(request, expand_subnet=True, expand_router=True,
expand_conns=True, **kwargs)
def _vpnservice_list(request, expand_subnet=False, expand_router=False,
expand_conns=False, **kwargs):
vpnservices = neutronclient(request).list_vpnservices(
**kwargs).get('vpnservices')
if expand_subnet:
subnets = neutron.subnet_list(request)
subnet_dict = OrderedDict((s.id, s) for s in subnets)
for s in vpnservices:
s['subnet_name'] = subnet_dict.get(s['subnet_id']).cidr
if expand_router:
routers = neutron.router_list(request)
router_dict = OrderedDict((r.id, r) for r in routers)
for s in vpnservices:
s['router_name'] = router_dict.get(s['router_id']).name_or_id
if expand_conns:
ipsecsiteconns = _ipsecsiteconnection_list(request, **kwargs)
for s in vpnservices:
s['ipsecsiteconns'] = [c.id for c in ipsecsiteconns
if c.vpnservice_id == s['id']]
return [VPNService(v) for v in vpnservices]
@profiler.trace
def vpnservice_get(request, vpnservice_id):
return _vpnservice_get(request, vpnservice_id, expand_subnet=True,
expand_router=True, expand_conns=True)
def _vpnservice_get(request, vpnservice_id, expand_subnet=False,
expand_router=False, expand_conns=False):
vpnservice = neutronclient(request).show_vpnservice(vpnservice_id).get(
'vpnservice')
if expand_subnet:
vpnservice['subnet'] = neutron.subnet_get(
request, vpnservice['subnet_id'])
if expand_router:
vpnservice['router'] = neutron.router_get(
request, vpnservice['router_id'])
if expand_conns:
ipsecsiteconns = _ipsecsiteconnection_list(request)
vpnservice['ipsecsiteconns'] = [c for c in ipsecsiteconns
if c.vpnservice_id == vpnservice['id']]
return VPNService(vpnservice)
@profiler.trace
def vpnservice_update(request, vpnservice_id, **kwargs):
vpnservice = neutronclient(request).update_vpnservice(
vpnservice_id, kwargs).get('vpnservice')
return VPNService(vpnservice)
@profiler.trace
def vpnservice_delete(request, vpnservice_id):
neutronclient(request).delete_vpnservice(vpnservice_id)
@profiler.trace
def ikepolicy_create(request, **kwargs):
"""Create IKEPolicy
:param request: request context
:param name: name for IKEPolicy
:param description: description for IKEPolicy
:param auth_algorithm: authorization algorithm for IKEPolicy
:param encryption_algorithm: encryption algorithm for IKEPolicy
:param ike_version: IKE version for IKEPolicy
:param lifetime: Lifetime Units and Value for IKEPolicy
:param pfs: Perfect Forward Secrecy for IKEPolicy
:param phase1_negotiation_mode: IKE Phase1 negotiation mode for IKEPolicy
"""
body = {'ikepolicy':
{'name': kwargs['name'],
'description': kwargs['description'],
'auth_algorithm': kwargs['auth_algorithm'],
'encryption_algorithm': kwargs['encryption_algorithm'],
'ike_version': kwargs['ike_version'],
'lifetime': kwargs['lifetime'],
'pfs': kwargs['pfs'],
'phase1_negotiation_mode': kwargs['phase1_negotiation_mode']}
}
ikepolicy = neutronclient(request).create_ikepolicy(body).get(
'ikepolicy')
return IKEPolicy(ikepolicy)
@profiler.trace
def ikepolicy_list(request, **kwargs):
return _ikepolicy_list(request, expand_conns=True, **kwargs)
def _ikepolicy_list(request, expand_conns=False, **kwargs):
ikepolicies = neutronclient(request).list_ikepolicies(
**kwargs).get('ikepolicies')
if expand_conns:
ipsecsiteconns = _ipsecsiteconnection_list(request, **kwargs)
for p in ikepolicies:
p['ipsecsiteconns'] = [c.id for c in ipsecsiteconns
if c.ikepolicy_id == p['id']]
return [IKEPolicy(v) for v in ikepolicies]
@profiler.trace
def ikepolicy_get(request, ikepolicy_id):
return _ikepolicy_get(request, ikepolicy_id, expand_conns=True)
def _ikepolicy_get(request, ikepolicy_id, expand_conns=False):
ikepolicy = neutronclient(request).show_ikepolicy(
ikepolicy_id).get('ikepolicy')
if expand_conns:
ipsecsiteconns = _ipsecsiteconnection_list(request)
ikepolicy['ipsecsiteconns'] = [c for c in ipsecsiteconns
if c.ikepolicy_id == ikepolicy['id']]
return IKEPolicy(ikepolicy)
@profiler.trace
def ikepolicy_update(request, ikepolicy_id, **kwargs):
ikepolicy = neutronclient(request).update_ikepolicy(
ikepolicy_id, kwargs).get('ikepolicy')
return IKEPolicy(ikepolicy)
@profiler.trace
def ikepolicy_delete(request, ikepolicy_id):
neutronclient(request).delete_ikepolicy(ikepolicy_id)
@profiler.trace
def ipsecpolicy_create(request, **kwargs):
"""Create IPSecPolicy
:param request: request context
:param name: name for IPSecPolicy
:param description: description for IPSecPolicy
:param auth_algorithm: authorization algorithm for IPSecPolicy
:param encapsulation_mode: encapsulation mode for IPSecPolicy
:param encryption_algorithm: encryption algorithm for IPSecPolicy
:param lifetime: Lifetime Units and Value for IPSecPolicy
:param pfs: Perfect Forward Secrecy for IPSecPolicy
:param transform_protocol: Transform Protocol for IPSecPolicy
"""
body = {'ipsecpolicy':
{'name': kwargs['name'],
'description': kwargs['description'],
'auth_algorithm': kwargs['auth_algorithm'],
'encapsulation_mode': kwargs['encapsulation_mode'],
'encryption_algorithm': kwargs['encryption_algorithm'],
'lifetime': kwargs['lifetime'],
'pfs': kwargs['pfs'],
'transform_protocol': kwargs['transform_protocol']}
}
ipsecpolicy = neutronclient(request).create_ipsecpolicy(body).get(
'ipsecpolicy')
return IPSecPolicy(ipsecpolicy)
@profiler.trace
def ipsecpolicy_list(request, **kwargs):
return _ipsecpolicy_list(request, expand_conns=True, **kwargs)
def _ipsecpolicy_list(request, expand_conns=False, **kwargs):
ipsecpolicies = neutronclient(request).list_ipsecpolicies(
**kwargs).get('ipsecpolicies')
if expand_conns:
ipsecsiteconns = _ipsecsiteconnection_list(request, **kwargs)
for p in ipsecpolicies:
p['ipsecsiteconns'] = [c.id for c in ipsecsiteconns
if c.ipsecpolicy_id == p['id']]
return [IPSecPolicy(v) for v in ipsecpolicies]
@profiler.trace
def ipsecpolicy_get(request, ipsecpolicy_id):
return _ipsecpolicy_get(request, ipsecpolicy_id, expand_conns=True)
def _ipsecpolicy_get(request, ipsecpolicy_id, expand_conns=False):
ipsecpolicy = neutronclient(request).show_ipsecpolicy(
ipsecpolicy_id).get('ipsecpolicy')
if expand_conns:
ipsecsiteconns = _ipsecsiteconnection_list(request)
ipsecpolicy['ipsecsiteconns'] = [c for c in ipsecsiteconns
if (c.ipsecpolicy_id ==
ipsecpolicy['id'])]
return IPSecPolicy(ipsecpolicy)
@profiler.trace
def ipsecpolicy_update(request, ipsecpolicy_id, **kwargs):
ipsecpolicy = neutronclient(request).update_ipsecpolicy(
ipsecpolicy_id, kwargs).get('ipsecpolicy')
return IPSecPolicy(ipsecpolicy)
@profiler.trace
def ipsecpolicy_delete(request, ipsecpolicy_id):
neutronclient(request).delete_ipsecpolicy(ipsecpolicy_id)
@profiler.trace
def ipsecsiteconnection_create(request, **kwargs):
"""Create IPSecSiteConnection
:param request: request context
:param name: name for IPSecSiteConnection
:param description: description for IPSecSiteConnection
:param dpd: dead peer detection action, interval and timeout
:param ikepolicy_id: IKEPolicy associated with this connection
:param initiator: initiator state
:param ipsecpolicy_id: IPsecPolicy associated with this connection
:param mtu: MTU size for the connection
:param peer_address: Peer gateway public address
:param peer_cidrs: remote subnet(s) in CIDR format
:param peer_id: Peer router identity for authentication"
:param psk: Pre-Shared Key string
:param vpnservice_id: VPNService associated with this connection
:param admin_state_up: admin state (default on)
"""
body = {'ipsec_site_connection':
{'name': kwargs['name'],
'description': kwargs['description'],
'dpd': kwargs['dpd'],
'ikepolicy_id': kwargs['ikepolicy_id'],
'initiator': kwargs['initiator'],
'ipsecpolicy_id': kwargs['ipsecpolicy_id'],
'mtu': kwargs['mtu'],
'peer_address': kwargs['peer_address'],
'peer_cidrs': kwargs['peer_cidrs'],
'peer_id': kwargs['peer_id'],
'psk': kwargs['psk'],
'vpnservice_id': kwargs['vpnservice_id'],
'admin_state_up': kwargs['admin_state_up']}
}
ipsecsiteconnection = neutronclient(request).create_ipsec_site_connection(
body).get('ipsec_site_connection')
return IPSecSiteConnection(ipsecsiteconnection)
@profiler.trace
@memoized
def ipsecsiteconnection_list(request, **kwargs):
return _ipsecsiteconnection_list(request, expand_ikepolicies=True,
expand_ipsecpolicies=True,
expand_vpnservices=True, **kwargs)
@memoized
def _ipsecsiteconnection_list(request, expand_ikepolicies=False,
expand_ipsecpolicies=False,
expand_vpnservices=False, **kwargs):
ipsecsiteconnections = neutronclient(request).list_ipsec_site_connections(
**kwargs).get('ipsec_site_connections')
if expand_ikepolicies:
ikepolicies = _ikepolicy_list(request)
policy_dict = OrderedDict((p.id, p) for p in ikepolicies)
for c in ipsecsiteconnections:
c['ikepolicy_name'] = policy_dict.get(c['ikepolicy_id']).name_or_id
if expand_ipsecpolicies:
ipsecpolicies = _ipsecpolicy_list(request)
policy_dict = OrderedDict((p.id, p) for p in ipsecpolicies)
for c in ipsecsiteconnections:
c['ipsecpolicy_name'] = policy_dict.get(c['ipsecpolicy_id']
).name_or_id
if expand_vpnservices:
vpnservices = _vpnservice_list(request)
service_dict = OrderedDict((s.id, s) for s in vpnservices)
for c in ipsecsiteconnections:
c['vpnservice_name'] = service_dict.get(c['vpnservice_id']
).name_or_id
return [IPSecSiteConnection(v) for v in ipsecsiteconnections]
@profiler.trace
def ipsecsiteconnection_get(request, ipsecsiteconnection_id):
return _ipsecsiteconnection_get(request, ipsecsiteconnection_id,
expand_ikepolicies=True,
expand_ipsecpolicies=True,
expand_vpnservices=True)
def _ipsecsiteconnection_get(request, ipsecsiteconnection_id,
expand_ikepolicies, expand_ipsecpolicies,
expand_vpnservices):
ipsecsiteconnection = neutronclient(request).show_ipsec_site_connection(
ipsecsiteconnection_id).get('ipsec_site_connection')
if expand_ikepolicies:
ipsecsiteconnection['ikepolicy'] = _ikepolicy_get(
request, ipsecsiteconnection['ikepolicy_id'])
if expand_ipsecpolicies:
ipsecsiteconnection['ipsecpolicy'] = _ipsecpolicy_get(
request, ipsecsiteconnection['ipsecpolicy_id'])
if expand_vpnservices:
ipsecsiteconnection['vpnservice'] = _vpnservice_get(
request, ipsecsiteconnection['vpnservice_id'])
return IPSecSiteConnection(ipsecsiteconnection)
@profiler.trace
def ipsecsiteconnection_update(request, ipsecsiteconnection_id, **kwargs):
ipsecsiteconnection = neutronclient(request).update_ipsec_site_connection(
ipsecsiteconnection_id, kwargs).get('ipsec_site_connection')
return IPSecSiteConnection(ipsecsiteconnection)
@profiler.trace
def ipsecsiteconnection_delete(request, ipsecsiteconnection_id):
neutronclient(request).delete_ipsec_site_connection(ipsecsiteconnection_id)

View File

@ -0,0 +1,323 @@
# Copyright 2013, Mirantis Inc
#
# 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.
import logging
from django.core.urlresolvers import reverse
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import messages
from neutron_vpnaas_dashboard import api as api_vpn
LOG = logging.getLogger(__name__)
class UpdateVPNService(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
vpnservice_id = forms.CharField(
label=_("ID"),
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
description = forms.CharField(
required=False, max_length=80, label=_("Description"))
admin_state_up = forms.BooleanField(label=_("Enable Admin State"),
required=False)
failure_url = 'horizon:project:vpn:index'
def handle(self, request, context):
try:
data = {'vpnservice': {'name': context['name'],
'description': context['description'],
'admin_state_up': context['admin_state_up'],
}}
vpnservice = api_vpn.vpnservice_update(
request, context['vpnservice_id'], **data)
msg = (_('VPN Service %s was successfully updated.')
% context['name'])
LOG.debug(msg)
messages.success(request, msg)
return vpnservice
except Exception as e:
msg = _('Failed to update VPN Service %s') % context['name']
LOG.info('%(msg)s: %(exception)s', {'msg': msg, 'exception': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateIKEPolicy(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
ikepolicy_id = forms.CharField(
label=_("ID"),
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
description = forms.CharField(
required=False, max_length=80, label=_("Description"))
# Currently this field has only one choice, so mark it as readonly.
auth_algorithm = forms.ChoiceField(
label=_("Authorization algorithm"),
choices=[('sha1', _('sha1'))],
widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
required=False)
encryption_algorithm = forms.ChoiceField(
label=_("Encryption algorithm"),
choices=[('3des', _('3des')),
('aes-128', _('aes-128')),
('aes-192', _('aes-192')),
('aes-256', _('aes-256'))],
required=False)
ike_version = forms.ChoiceField(
label=_("IKE version"),
choices=[('v1', _('v1')),
('v2', _('v2'))],
required=False)
# Currently this field has only one choice, so mark it as readonly.
lifetime_units = forms.ChoiceField(
label=_("Lifetime units for IKE keys"),
choices=[('seconds', _('seconds'))],
widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
required=False)
lifetime_value = forms.IntegerField(
min_value=60,
label=_("Lifetime value for IKE keys"),
help_text=_("Equal to or greater than 60"),
required=False)
pfs = forms.ChoiceField(
label=_("Perfect Forward Secrecy"),
choices=[('group2', _('group2')),
('group5', _('group5')),
('group14', _('group14'))],
required=False)
# Currently this field has only one choice, so mark it as readonly.
phase1_negotiation_mode = forms.ChoiceField(
label=_("IKE Phase1 negotiation mode"),
choices=[('main', 'main')],
widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
required=False)
failure_url = 'horizon:project:vpn:index'
def handle(self, request, context):
try:
data = {'ikepolicy':
{'name': context['name'],
'description': context['description'],
'auth_algorithm': context['auth_algorithm'],
'encryption_algorithm': context['encryption_algorithm'],
'ike_version': context['ike_version'],
'lifetime': {'units': context['lifetime_units'],
'value': context['lifetime_value']},
'pfs': context['pfs'],
'phase1_negotiation_mode':
context['phase1_negotiation_mode'],
}}
ikepolicy = api_vpn.ikepolicy_update(
request, context['ikepolicy_id'], **data)
msg = (_('IKE Policy %s was successfully updated.')
% context['name'])
LOG.debug(msg)
messages.success(request, msg)
return ikepolicy
except Exception as e:
msg = _('Failed to update IKE Policy %s') % context['name']
LOG.info('%(msg)s: %(exception)s', {'msg': msg, 'exception': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateIPSecPolicy(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
ipsecpolicy_id = forms.CharField(
label=_("ID"),
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
description = forms.CharField(
required=False, max_length=80, label=_("Description"))
# Currently this field has only one choice, so mark it as readonly.
auth_algorithm = forms.ChoiceField(
label=_("Authorization algorithm"),
choices=[('sha1', _('sha1'))],
widget=forms.TextInput(attrs={'readonly': 'readonly'}),
required=False)
encapsulation_mode = forms.ChoiceField(
label=_("Encapsulation mode"),
choices=[('tunnel', _('tunnel')),
('transport', _('transport'))],
required=False)
encryption_algorithm = forms.ChoiceField(
label=_("Encryption algorithm"),
choices=[('3des', _('3des')),
('aes-128', _('aes-128')),
('aes-192', _('aes-192')),
('aes-256', _('aes-256'))],
required=False)
# Currently this field has only one choice, so mark it as readonly.
lifetime_units = forms.ChoiceField(
label=_("Lifetime units"),
choices=[('seconds', _('seconds'))],
widget=forms.ThemableSelectWidget(attrs={'readonly': 'readonly'}),
required=False)
lifetime_value = forms.IntegerField(
min_value=60,
label=_("Lifetime value"),
help_text=_("Equal to or greater than 60"),
required=False)
pfs = forms.ChoiceField(
label=_("Perfect Forward Secrecy"),
choices=[('group2', _('group2')),
('group5', _('group5')),
('group14', _('group14'))],
required=False)
transform_protocol = forms.ChoiceField(
label=_("Transform Protocol"),
choices=[('esp', _('esp')),
('ah', _('ah')),
('ah-esp', _('ah-esp'))],
required=False)
failure_url = 'horizon:project:vpn:index'
def handle(self, request, context):
try:
data = {'ipsecpolicy':
{'name': context['name'],
'description': context['description'],
'auth_algorithm': context['auth_algorithm'],
'encapsulation_mode': context['encapsulation_mode'],
'encryption_algorithm': context['encryption_algorithm'],
'lifetime': {'units': context['lifetime_units'],
'value': context['lifetime_value']},
'pfs': context['pfs'],
'transform_protocol': context['transform_protocol'],
}}
ipsecpolicy = api_vpn.ipsecpolicy_update(
request, context['ipsecpolicy_id'], **data)
msg = (_('IPSec Policy %s was successfully updated.')
% context['name'])
LOG.debug(msg)
messages.success(request, msg)
return ipsecpolicy
except Exception as e:
msg = _('Failed to update IPSec Policy %s') % context['name']
LOG.info('%(msg)s: %(exception)s', {'msg': msg, 'exception': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)
class UpdateIPSecSiteConnection(forms.SelfHandlingForm):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
ipsecsiteconnection_id = forms.CharField(
label=_("ID"),
widget=forms.TextInput(attrs={'readonly': 'readonly'}))
description = forms.CharField(
required=False, max_length=80, label=_("Description"))
peer_address = forms.IPField(
label=_("Peer gateway public IPv4/IPv6 Address or FQDN"),
help_text=_("Peer gateway public IPv4/IPv6 address or FQDN for "
"the VPN Connection"),
version=forms.IPv4 | forms.IPv6,
mask=False)
peer_id = forms.IPField(
label=_("Peer router identity for authentication (Peer ID)"),
help_text=_("Peer router identity for authentication. "
"Can be IPv4/IPv6 address, e-mail, key ID, or FQDN"),
version=forms.IPv4 | forms.IPv6,
mask=False)
peer_cidrs = forms.MultiIPField(
label=_("Remote peer subnet(s)"),
help_text=_("Remote peer subnet(s) address(es) "
"with mask(s) in CIDR format "
"separated with commas if needed "
"(e.g. 20.1.0.0/24, 21.1.0.0/24)"),
version=forms.IPv4 | forms.IPv6,
mask=True)
psk = forms.CharField(
widget=forms.PasswordInput(render_value=True),
max_length=80, label=_("Pre-Shared Key (PSK) string"))
mtu = forms.IntegerField(
min_value=68,
required=False,
label=_("Maximum Transmission Unit size for the connection"),
help_text=_("Equal to or greater than 68 if the local subnet is IPv4. "
"Equal to or greater than 1280 if the local subnet "
"is IPv6."))
dpd_action = forms.ChoiceField(
label=_("Dead peer detection actions"),
required=False,
choices=[('hold', _('hold')),
('clear', _('clear')),
('disabled', _('disabled')),
('restart', _('restart')),
('restart-by-peer', _('restart-by-peer'))])
dpd_interval = forms.IntegerField(
min_value=1,
required=False,
label=_("Dead peer detection interval"),
help_text=_("Valid integer lesser than the DPD timeout"))
dpd_timeout = forms.IntegerField(
min_value=1,
required=False,
label=_("Dead peer detection timeout"),
help_text=_("Valid integer greater than the DPD interval"))
initiator = forms.ChoiceField(
label=_("Initiator state"),
required=False,
choices=[('bi-directional', _('bi-directional')),
('response-only', _('response-only'))])
admin_state_up = forms.BooleanField(label=_("Enable Admin State"),
required=False)
failure_url = 'horizon:project:vpn:index'
def clean(self):
cleaned_data = super(UpdateIPSecSiteConnection, self).clean()
interval = cleaned_data.get('dpd_interval')
timeout = cleaned_data.get('dpd_timeout')
if not interval < timeout:
msg = _("DPD Timeout must be greater than DPD Interval")
self._errors['dpd_timeout'] = self.error_class([msg])
return cleaned_data
def handle(self, request, context):
try:
data = {'ipsec_site_connection':
{'name': context['name'],
'description': context['description'],
'peer_address': context['peer_address'],
'peer_id': context['peer_id'],
'peer_cidrs': context[
'peer_cidrs'].replace(" ", "").split(","),
'psk': context['psk'],
'mtu': context['mtu'],
'dpd': {'action': context['dpd_action'],
'interval': context['dpd_interval'],
'timeout': context['dpd_timeout']},
'initiator': context['initiator'],
'admin_state_up': context['admin_state_up'],
}}
ipsecsiteconnection = api_vpn.ipsecsiteconnection_update(
request, context['ipsecsiteconnection_id'], **data)
msg = (_('IPSec Site Connection %s was successfully updated.')
% context['name'])
LOG.debug(msg)
messages.success(request, msg)
return ipsecsiteconnection
except Exception as e:
msg = (_('Failed to update IPSec Site Connection %s')
% context['name'])
LOG.info('%(msg)s: %(exception)s', {'msg': msg, 'exception': e})
redirect = reverse(self.failure_url)
exceptions.handle(request, msg, redirect=redirect)

View File

@ -0,0 +1,47 @@
# Copyright 2013, Mirantis Inc
#
# 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.
import logging
from django.utils.translation import ugettext_lazy as _
import horizon
from openstack_dashboard.api import neutron
LOG = logging.getLogger(__name__)
class VPN(horizon.Panel):
name = _("VPN")
slug = 'vpn'
permissions = ('openstack.services.network',)
def allowed(self, context):
request = context['request']
if not request.user.has_perms(self.permissions):
return False
try:
if not neutron.is_service_enabled(request,
config_name='enable_vpn',
ext_name='vpnaas'):
return False
except Exception:
LOG.error("Call to list enabled services failed. This is likely "
"due to a problem communicating with the Neutron "
"endpoint. VPN panel will not be displayed.")
return False
if not super(VPN, self).allowed(context):
return False
return True

View File

@ -0,0 +1,465 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from django.core.urlresolvers import reverse
from django import template
from django.utils.translation import pgettext_lazy
from django.utils.translation import ugettext_lazy as _
from django.utils.translation import ungettext_lazy
from horizon import exceptions
from horizon import tables
from openstack_dashboard import policy
from neutron_vpnaas_dashboard import api
forbid_updates = set(["PENDING_CREATE", "PENDING_UPDATE", "PENDING_DELETE"])
class AddIKEPolicyLink(tables.LinkAction):
name = "addikepolicy"
verbose_name = _("Add IKE Policy")
url = "horizon:project:vpn:addikepolicy"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_ikepolicy"),)
class AddIPSecPolicyLink(tables.LinkAction):
name = "addipsecpolicy"
verbose_name = _("Add IPSec Policy")
url = "horizon:project:vpn:addipsecpolicy"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_ipsecpolicy"),)
class AddVPNServiceLink(tables.LinkAction):
name = "addvpnservice"
verbose_name = _("Add VPN Service")
url = "horizon:project:vpn:addvpnservice"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_vpnservice"),)
class AddIPSecSiteConnectionLink(tables.LinkAction):
name = "addipsecsiteconnection"
verbose_name = _("Add IPSec Site Connection")
url = "horizon:project:vpn:addipsecsiteconnection"
classes = ("ajax-modal",)
icon = "plus"
policy_rules = (("network", "create_ipsec_site_connection"),)
class DeleteVPNServiceLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deletevpnservice"
policy_rules = (("network", "delete_vpnservice"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete VPN Service",
u"Delete VPN Services",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of VPN Service",
u"Scheduled deletion of VPN Services",
count
)
def allowed(self, request, datum=None):
if datum and datum.ipsecsiteconns:
return False
return True
def delete(self, request, obj_id):
try:
api.vpn.vpnservice_delete(request, obj_id)
except Exception as e:
exceptions.handle(
request, _('Unable to delete VPN Service. %s') % e)
class DeleteIKEPolicyLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deleteikepolicy"
policy_rules = (("network", "delete_ikepolicy"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete IKE Policy",
u"Delete IKE Policies",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of IKE Policy",
u"Scheduled deletion of IKE Policies",
count
)
def allowed(self, request, datum=None):
if datum and datum.ipsecsiteconns:
return False
return True
def delete(self, request, obj_id):
try:
api.vpn.ikepolicy_delete(request, obj_id)
except Exception as e:
exceptions.handle(
request, _('Unable to delete IKE Policy. %s') % e)
class DeleteIPSecPolicyLink(policy.PolicyTargetMixin, tables.DeleteAction):
name = "deleteipsecpolicy"
policy_rules = (("network", "delete_ipsecpolicy"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete IPSec Policy",
u"Delete IPSec Policies",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of IPSec Policy",
u"Scheduled deletion of IPSec Policies",
count
)
def allowed(self, request, datum=None):
if datum and datum.ipsecsiteconns:
return False
return True
def delete(self, request, obj_id):
try:
api.vpn.ipsecpolicy_delete(request, obj_id)
except Exception as e:
exceptions.handle(
request, _('Unable to delete IPSec Policy. %s') % e)
class DeleteIPSecSiteConnectionLink(policy.PolicyTargetMixin,
tables.DeleteAction):
name = "deleteipsecsiteconnection"
policy_rules = (("network", "delete_ipsec_site_connection"),)
@staticmethod
def action_present(count):
return ungettext_lazy(
u"Delete IPSec Site Connection",
u"Delete IPSec Site Connections",
count
)
@staticmethod
def action_past(count):
return ungettext_lazy(
u"Scheduled deletion of IPSec Site Connection",
u"Scheduled deletion of IPSec Site Connections",
count
)
def delete(self, request, obj_id):
try:
api.vpn.ipsecsiteconnection_delete(request, obj_id)
except Exception as e:
exceptions.handle(
request, _('Unable to delete IPSec Site Connection. %s') % e)
class UpdateVPNServiceLink(tables.LinkAction):
name = "update_vpnservice"
verbose_name = _("Edit VPN Service")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_vpnservice"),)
def get_link_url(self, vpnservice):
return reverse("horizon:project:vpn:update_vpnservice",
kwargs={'vpnservice_id': vpnservice.id})
def allowed(self, request, datum=None):
if datum and datum.status not in forbid_updates:
return True
return False
class UpdateIKEPolicyLink(tables.LinkAction):
name = "updateikepolicy"
verbose_name = _("Edit IKE Policy")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_ikepolicy"),)
def get_link_url(self, ikepolicy):
return reverse("horizon:project:vpn:update_ikepolicy",
kwargs={'ikepolicy_id': ikepolicy.id})
def allowed(self, request, datum=None):
return not datum['ipsecsiteconns']
class UpdateIPSecPolicyLink(tables.LinkAction):
name = "updateipsecpolicy"
verbose_name = _("Edit IPSec Policy")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_ipsecpolicy"),)
def get_link_url(self, ipsecpolicy):
return reverse("horizon:project:vpn:update_ipsecpolicy",
kwargs={'ipsecpolicy_id': ipsecpolicy.id})
def allowed(self, request, datum=None):
return not datum['ipsecsiteconns']
class UpdateIPSecSiteConnectionLink(tables.LinkAction):
name = "updateipsecsiteconnection"
verbose_name = _("Edit Connection")
classes = ("ajax-modal", "btn-update",)
policy_rules = (("network", "update_ipsec_site_connection"),)
def get_link_url(self, ipsecsiteconnection):
return reverse("horizon:project:vpn:update_ipsecsiteconnection",
kwargs={'ipsecsiteconnection_id':
ipsecsiteconnection.id})
def allowed(self, request, datum=None):
if datum and datum.status not in forbid_updates:
return True
return False
STATUS_CHOICES = (
("active", True),
("down", True),
("created", True),
("error", False),
("inactive", False),
)
STATUS_DISPLAY_CHOICES = (
("active", pgettext_lazy("Current status of an IPSec Site Connection"
" and VPN Service", u"Active")),
("down", pgettext_lazy("Current status of an IPSec Site Connection"
" and VPN Service", u"Down")),
("error", pgettext_lazy("Current status of an IPSec Site Connection"
" and VPN Service", u"Error")),
("created", pgettext_lazy("Current status of an IPSec Site Connection"
" and VPN Service", u"Created")),
("pending_create", pgettext_lazy("Current status of an"
" IPSec Site Connection and VPN Service",
u"Pending Create")),
("pending_update", pgettext_lazy("Current status of an"
" IPSec Site Connection and VPN Service",
u"Pending Update")),
("pending_delete", pgettext_lazy("Current status of an"
" IPSec Site Connection and VPN Service",
u"Pending Delete")),
("inactive", pgettext_lazy("Current status of an IPSec Site Connection"
" and VPN Service", u"Inactive")),
)
class UpdateIPSecSiteConnectionRow(tables.Row):
ajax = True
def get_data(self, request, conn_id):
conn = api.vpn.ipsecsiteconnection_get(request, conn_id)
conn.ikepolicy_name = conn['ikepolicy'].get('name',
conn['ikepolicy_id'])
conn.ipsecpolicy_name = conn['ipsecpolicy'].get('name',
conn['ipsecpolicy_id'])
conn.vpnservice_name = conn['vpnservice'].get('name',
conn['vpnservice_id'])
return conn
class IPSSCFilterAction(tables.FilterAction):
name = 'IPSSC_project_IKEPolicies'
filter_type = 'server'
filter_choices = (
('name', _("Name ="), True),
('vpnservice', _("VPN Service ="), True),
('vpnservice_id', _("VPN Service ID ="), True),
('ikepolicy', _("IKE Policy ="), True),
('ikepolicy_id', _("IKE Policy ID ="), True),
('ipsecpolicy', _("IPSec Policy ="), True),
('ipsecpolicy_id', _("IPSec Policy ID ="), True),
('status', _("Status ="), True)
)
class IPSecSiteConnectionsTable(tables.DataTable):
id = tables.Column('id', hidden=True)
name = tables.Column('name_or_id', verbose_name=_('Name'),
link="horizon:project:vpn:ipsecsiteconnectiondetails")
description = tables.Column('description', verbose_name=_('Description'))
vpnservice_name = tables.Column('vpnservice_name',
verbose_name=_('VPN Service'))
ikepolicy_name = tables.Column('ikepolicy_name',
verbose_name=_('IKE Policy'))
ipsecpolicy_name = tables.Column('ipsecpolicy_name',
verbose_name=_('IPSec Policy'))
status = tables.Column("status",
verbose_name=_("Status"),
status=True,
status_choices=STATUS_CHOICES,
display_choices=STATUS_DISPLAY_CHOICES)
def get_object_display(self, ipsecsiteconnection):
return ipsecsiteconnection.name_or_id
class Meta(object):
name = "ipsecsiteconnectionstable"
verbose_name = _("IPSec Site Connections")
status_columns = ['status']
row_class = UpdateIPSecSiteConnectionRow
table_actions = (AddIPSecSiteConnectionLink,
DeleteIPSecSiteConnectionLink,
IPSSCFilterAction)
row_actions = (UpdateIPSecSiteConnectionLink,
DeleteIPSecSiteConnectionLink)
def get_local_ips(vpn):
template_name = 'project/vpn/_vpn_ips.html'
context = {"external_v4_ip": vpn.get('external_v4_ip'),
"external_v6_ip": vpn.get('external_v6_ip')}
return template.loader.render_to_string(template_name, context)
class UpdateVPNServiceRow(tables.Row):
ajax = True
def get_data(self, request, vpn_id):
vpn = api.vpn.vpnservice_get(request, vpn_id)
vpn.router_name = vpn['router'].get('name', vpn['router_id'])
vpn.subnet_name = vpn['subnet'].get('cidr', vpn['subnet_id'])
return vpn
class VPNServicesFilterAction(tables.FilterAction):
name = 'vpnservices_project_IKEPolicies'
filter_type = 'server'
filter_choices = (
('name', _("Name ="), True),
('subnet_id', _("Subnet ID ="), True),
('subnet_name', _("Subnet ="), True),
('router_id', _("Router ID ="), True),
('router_name', _("Router ="), True),
)
class VPNServicesTable(tables.DataTable):
id = tables.Column('id', hidden=True)
name = tables.Column("name_or_id", verbose_name=_('Name'),
link="horizon:project:vpn:vpnservicedetails")
description = tables.Column('description', verbose_name=_('Description'))
local_ips = tables.Column(get_local_ips,
verbose_name=_("Local Side Public IPs"))
subnet_name = tables.Column('subnet_name', verbose_name=_('Subnet'))
router_name = tables.Column('router_name', verbose_name=_('Router'))
status = tables.Column("status",
verbose_name=_("Status"),
status=True,
status_choices=STATUS_CHOICES,
display_choices=STATUS_DISPLAY_CHOICES)
def get_object_display(self, vpnservice):
return vpnservice.name_or_id
class Meta(object):
name = "vpnservicestable"
verbose_name = _("VPN Services")
status_columns = ['status']
row_class = UpdateVPNServiceRow
table_actions = (AddVPNServiceLink,
DeleteVPNServiceLink,
VPNServicesFilterAction)
row_actions = (UpdateVPNServiceLink, DeleteVPNServiceLink)
class PoliciesFilterAction(tables.FilterAction):
name = 'filter_project_IKEPolicies'
filter_type = 'server'
filter_choices = (
('name', _("Name ="), True),
('auth_algorithm', _("Authorization algorithm ="), True),
('encryption_algorithm', _("Encryption algorithm ="), True),
('pfs', _("PFS ="), True),
)
class IKEPoliciesTable(tables.DataTable):
id = tables.Column('id', hidden=True)
name = tables.Column("name_or_id", verbose_name=_('Name'),
link="horizon:project:vpn:ikepolicydetails")
description = tables.Column('description', verbose_name=_('Description'))
auth_algorithm = tables.Column('auth_algorithm',
verbose_name=_('Authorization algorithm'))
encryption_algorithm = tables.Column(
'encryption_algorithm',
verbose_name=_('Encryption algorithm'))
pfs = tables.Column("pfs", verbose_name=_('PFS'))
def get_object_display(self, ikepolicy):
return ikepolicy.name_or_id
class Meta(object):
name = "ikepoliciestable"
verbose_name = _("IKE Policies")
table_actions = (AddIKEPolicyLink,
DeleteIKEPolicyLink,
PoliciesFilterAction)
row_actions = (UpdateIKEPolicyLink, DeleteIKEPolicyLink)
class IPSecPoliciesTable(tables.DataTable):
id = tables.Column('id', hidden=True)
name = tables.Column("name_or_id", verbose_name=_('Name'),
link="horizon:project:vpn:ipsecpolicydetails")
description = tables.Column('description', verbose_name=_('Description'))
auth_algorithm = tables.Column('auth_algorithm',
verbose_name=_('Authorization algorithm'))
encryption_algorithm = tables.Column(
'encryption_algorithm',
verbose_name=_('Encryption algorithm'))
pfs = tables.Column("pfs", verbose_name=_('PFS'))
def get_object_display(self, ipsecpolicy):
return ipsecpolicy.name_or_id
class Meta(object):
name = "ipsecpoliciestable"
verbose_name = _("IPSec Policies")
table_actions = (AddIPSecPolicyLink,
DeleteIPSecPolicyLink,
PoliciesFilterAction)
row_actions = (UpdateIPSecPolicyLink, DeleteIPSecPolicyLink)

View File

@ -0,0 +1,233 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import tables as htables
from horizon import tabs
from openstack_dashboard import api
from neutron_vpnaas_dashboard import api as api_vpn
from neutron_vpnaas_dashboard.dashboards.project import tables
class IPSecSiteConnectionsTab(tabs.TableTab, htables.DataTableView):
table_classes = (tables.IPSecSiteConnectionsTable,)
name = _("IPSec Site Connections")
slug = "ipsecsiteconnections"
template_name = ("horizon/common/_detail_table.html")
FILTERS_MAPPING = {'admin_state_up': {_("up"): True, _("down"): False}}
def get_ipsecsiteconnectionstable_data(self):
try:
filters = self.get_filters()
tenant_id = self.request.user.tenant_id
if 'vpnservice' in filters:
filters['vpnservice_id'] = \
[v.id for v in api_vpn.vpnservice_list(
self.tab_group.request, tenant_id=tenant_id,
name=filters['vpnservice'])]
del filters['vpnservice']
if 'ikepolicy' in filters:
filters['ikepolicy_id'] = \
[i.id for i in api_vpn.ikepolicy_list(
self.tab_group.request, tenant_id=tenant_id,
name=filters['ikepolicy'])]
del filters['ikepolicy']
if 'ipsecpolicy' in filters:
filters['ipsecpolicy_id'] = \
[i.id for i in api_vpn.ipsecpolicy_list(
self.tab_group.request, tenant_id=tenant_id,
name=filters['ipsecpolicy'])]
del filters['ipsecpolicy']
ipsecsiteconnections = api_vpn.ipsecsiteconnection_list(
self.tab_group.request, tenant_id=tenant_id, **filters)
except Exception:
ipsecsiteconnections = []
exceptions.handle(
self.tab_group.request,
_('Unable to retrieve IPSec Site Connections list.'))
return ipsecsiteconnections
def get_filters(self):
self.table = self._tables['ipsecsiteconnectionstable']
self.handle_server_filter(self.request, table=self.table)
self.update_server_filter_action(self.request, table=self.table)
return super(IPSecSiteConnectionsTab,
self).get_filters(filters_map=self.FILTERS_MAPPING)
class VPNServicesTab(tabs.TableTab, htables.DataTableView):
table_classes = (tables.VPNServicesTable,)
name = _("VPN Services")
slug = "vpnservices"
template_name = ("horizon/common/_detail_table.html")
def get_vpnservicestable_data(self):
try:
filters = self.get_filters()
tenant_id = self.request.user.tenant_id
if 'subnet_name' in filters:
subnets = api.neutron.subnet_list(self.tab_group.request,
tenant_id=tenant_id,
cidr=filters['subnet_name'])
subnets_ids = [n.id for n in subnets]
del filters['subnet_name']
if not subnets_ids:
return []
filters['subnet_id'] = subnets_ids
if 'router_name' in filters:
routers = api.neutron.router_list(self.tab_group.request,
tenant_id=tenant_id,
name=filters['router_name'])
routers_ids = [r.id for r in routers]
if not routers:
return []
filters['router_id'] = routers_ids
vpnservices = api_vpn.vpnservice_list(
self.tab_group.request, tenant_id=tenant_id, **filters)
except Exception:
vpnservices = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve VPN Services list.'))
return vpnservices
def get_filters(self):
self.table = self._tables['vpnservicestable']
self.handle_server_filter(self.request, table=self.table)
self.update_server_filter_action(self.request, table=self.table)
return super(VPNServicesTab, self).get_filters()
class IKEPoliciesTab(tabs.TableTab, htables.DataTableView):
table_classes = (tables.IKEPoliciesTable,)
name = _("IKE Policies")
slug = "ikepolicies"
template_name = ("horizon/common/_detail_table.html")
def get_ikepoliciestable_data(self):
try:
filters = self.get_filters()
tenant_id = self.request.user.tenant_id
ikepolicies = api_vpn.ikepolicy_list(
self.tab_group.request, tenant_id=tenant_id, **filters)
except Exception:
ikepolicies = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve IKE Policies list.'))
return ikepolicies
def get_filters(self):
self.table = self._tables['ikepoliciestable']
self.handle_server_filter(self.request, table=self.table)
self.update_server_filter_action(self.request, table=self.table)
return super(IKEPoliciesTab, self).get_filters()
class IPSecPoliciesTab(tabs.TableTab, htables.DataTableView):
table_classes = (tables.IPSecPoliciesTable,)
name = _("IPSec Policies")
slug = "ipsecpolicies"
template_name = ("horizon/common/_detail_table.html")
def get_ipsecpoliciestable_data(self):
try:
filters = self.get_filters()
tenant_id = self.request.user.tenant_id
ipsecpolicies = api_vpn.ipsecpolicy_list(
self.tab_group.request, tenant_id=tenant_id, **filters)
except Exception:
ipsecpolicies = []
exceptions.handle(self.tab_group.request,
_('Unable to retrieve IPSec Policies list.'))
return ipsecpolicies
def get_filters(self):
self.table = self._tables['ipsecpoliciestable']
self.handle_server_filter(self.request, table=self.table)
self.update_server_filter_action(self.request, table=self.table)
return super(IPSecPoliciesTab, self).get_filters()
class VPNTabs(tabs.TabGroup):
slug = "vpntabs"
tabs = (IKEPoliciesTab, IPSecPoliciesTab,
VPNServicesTab, IPSecSiteConnectionsTab,)
sticky = True
class IKEPolicyDetailsTab(tabs.Tab):
name = _("IKE Policy Details")
slug = "ikepolicydetails"
template_name = "project/vpn/_ikepolicy_details.html"
def get_context_data(self, request):
ikepolicy = self.tab_group.kwargs['ikepolicy']
return {'ikepolicy': ikepolicy}
class IKEPolicyDetailsTabs(tabs.TabGroup):
slug = "ikepolicytabs"
tabs = (IKEPolicyDetailsTab,)
class IPSecPolicyDetailsTab(tabs.Tab):
name = _("IPSec Policy Details")
slug = "ipsecpolicydetails"
template_name = "project/vpn/_ipsecpolicy_details.html"
def get_context_data(self, request):
ipsecpolicy = self.tab_group.kwargs['ipsecpolicy']
return {'ipsecpolicy': ipsecpolicy}
class IPSecPolicyDetailsTabs(tabs.TabGroup):
slug = "ipsecpolicytabs"
tabs = (IPSecPolicyDetailsTab,)
class VPNServiceDetailsTab(tabs.Tab):
name = _("VPN Service Details")
slug = "vpnservicedetails"
template_name = "project/vpn/_vpnservice_details.html"
def get_context_data(self, request):
vpnservice = self.tab_group.kwargs['vpnservice']
return {'vpnservice': vpnservice}
class VPNServiceDetailsTabs(tabs.TabGroup):
slug = "vpnservicetabs"
tabs = (VPNServiceDetailsTab,)
class IPSecSiteConnectionDetailsTab(tabs.Tab):
name = _("IPSec Site Connection Details")
slug = "ipsecsiteconnectiondetails"
template_name = "project/vpn/_ipsecsiteconnection_details.html"
def get_context_data(self, request):
ipsecsiteconnection = self.tab_group.kwargs['ipsecsiteconnection']
return {'ipsecsiteconnection': ipsecsiteconnection}
class IPSecSiteConnectionDetailsTabs(tabs.TabGroup):
slug = "ipsecsiteconnectiontabs"
tabs = (IPSecSiteConnectionDetailsTab,)

View File

@ -0,0 +1,20 @@
{% load i18n %}
<p>{% trans "Create IKE Policy for current project." %}</p>
<p>{% trans "An IKE policy is an association of the following attributes:" %}</p>
<dl class="dl-readable">
<dt>{% trans 'Authorization algorithm' %}</dt>
<dd>{% trans 'Auth algorithm limited to SHA1 only.' %}</dd>
<dt>{% trans 'Encryption algorithm' %}</dt>
<dd>{% trans 'The type of algorithm (3des, aes-128, aes-192, aes-256) used in the IKE Policy.' %}</dd>
<dt>{% trans 'IKE version' %}</dt>
<dd>{% trans 'The type of version (v1/v2) that needs to be filtered.' %}</dd>
<dt>{% trans 'Lifetime' %}</dt>
<dd>{% trans "Life time consists of units and value. Units in 'seconds' and the default value is 3600." %}</dd>
<dt>{% trans 'Perfect Forward Secrecy' %}</dt>
<dd>{% trans 'PFS limited to using Diffie-Hellman groups 2, 5 (default) and 14.' %}</dd>
<dt>{% trans 'IKE Phase 1 negotiation mode' %}</dt>
<dd>{% trans "Limited to 'main' mode only." %}</dd>
</dl>
<p>{% trans "All fields are optional." %}</p>

View File

@ -0,0 +1,19 @@
{% load i18n %}
<p>{% trans 'Create IPSec Policy for current project.' %}</p>
<p>{% trans 'An IPSec policy is an association of the following attributes' %}</p>
<dl class="dl-readable">
<dt>{% trans 'Authorization algorithm' %}</dt>
<dd>{% trans 'Auth algorithm limited to SHA1 only.' %}</dd>
<dt>{% trans 'Encapsulation mode' %}</dt>
<dd>{% trans 'The type of IPsec tunnel (tunnel/transport) to be used.' %}</dd>
<dt>{% trans 'Encryption algorithm' %}</dt>
<dd>{% trans 'The type of algorithm (3des, aes-128, aes-192, aes-256) used in the IPSec Policy.' %}</dd>
<dt>{% trans 'Lifetime' %}</dt>
<dd>{% trans "Life time consists of units and value. Units in 'seconds' and the default value is 3600." %}</dd>
<dt>{% trans 'Perfect Forward Secrecy' %}</dt>
<dd>{% trans 'PFS limited to using Diffie-Hellman groups 2, 5 (default) and 14.' %}</dd>
<dt>{% trans 'Transform Protocol' %}</dt>
<dd>{% trans 'The type of protocol (esp, ah, ah-esp) used in IPSec Policy.' %}</dd>
</dl>
<p>{% trans 'All fields are optional.' %}</p>

View File

@ -0,0 +1,7 @@
{% load i18n %}
<p>{% trans "Create VPN service for current project." %}</p>
<p>{% trans "The VPN service is attached to a router and references to a single subnet to push to a remote site." %}</p>
<p>{% trans "Specify a name, description, router, and subnet for the VPN Service." %}</p>
<p>{% trans "Admin State is enabled by default." %}</p>
<p>{% trans "The router, subnet and admin state fields require to be enabled. All others are optional." %} </p>

View File

@ -0,0 +1,38 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd data-display="{{ ikepolicy.name_or_id }}">{{ ikepolicy.name|default:_("None") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ ikepolicy.description|default:_("None") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ ikepolicy.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ ikepolicy.tenant_id }}</dd>
<dt>{% trans "Authorization algorithm" %}</dt>
<dd>{{ ikepolicy.auth_algorithm }}</dd>
<dt>{% trans "Encryption algorithm" %}</dt>
<dd>{{ ikepolicy.encryption_algorithm }}</dd>
<dt>{% trans "IKE version" %}</dt>
<dd>{{ ikepolicy.ike_version }}</dd>
<dt>{% trans "Lifetime Units" %}</dt>
<dd>{{ ikepolicy.lifetime.units }}</dd>
<dt>{% trans "Lifetime Value" %}</dt>
<dd>{{ ikepolicy.lifetime.value }}</dd>
<dt>{% trans "Perfect Forward Secrecy" %}</dt>
<dd>{{ ikepolicy.pfs }}</dd>
<dt>{% trans "IKE Phase1 negotiation mode" %}</dt>
<dd>{{ ikepolicy.phase1_negotiation_mode }}</dd>
</dl>
</div>

View File

@ -0,0 +1,38 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd data-display="{{ ipsecpolicy.name_or_id }}">{{ ipsecpolicy.name|default:_("None") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ ipsecpolicy.description|default:_("None") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ ipsecpolicy.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ ipsecpolicy.tenant_id }}</dd>
<dt>{% trans "Authorization algorithm" %}</dt>
<dd>{{ ipsecpolicy.auth_algorithm }}</dd>
<dt>{% trans "Encapsulation mode" %}</dt>
<dd>{{ ipsecpolicy.encapsulation_mode }}</dd>
<dt>{% trans "Encryption algorithm" %}</dt>
<dd>{{ ipsecpolicy.encryption_algorithm }}</dd>
<dt>{% trans "Lifetime Units" %}</dt>
<dd>{{ ipsecpolicy.lifetime.units }}</dd>
<dt>{% trans "Lifetime Value" %}</dt>
<dd>{{ ipsecpolicy.lifetime.value }}</dd>
<dt>{% trans "Perfect Forward Secrecy" %}</dt>
<dd>{{ ipsecpolicy.pfs }}</dd>
<dt>{% trans "Transform Protocol" %}</dt>
<dd>{{ ipsecpolicy.transform_protocol }}</dd>
</dl>
</div>

View File

@ -0,0 +1,69 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd data-display="{{ ipsecsiteconnection.name_or_id }}">{{ ipsecsiteconnection.name|default:_("None") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ ipsecsiteconnection.description|default:_("None") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ ipsecsiteconnection.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ ipsecsiteconnection.tenant_id }}</dd>
<dt>{% trans "VPN Service" %}</dt>
{% url 'horizon:project:vpn:vpnservicedetails' ipsecsiteconnection.vpnservice_id as vpnservice_url %}
<dd><a href="{{ vpnservice_url }}">{{ ipsecsiteconnection.vpnservice.name_or_id }}</a></dd>
<dt>{% trans "IKE Policy" %}</dt>
{% url 'horizon:project:vpn:ikepolicydetails' ipsecsiteconnection.ikepolicy_id as ikepolicy_url %}
<dd><a href="{{ ikepolicy_url }}">{{ ipsecsiteconnection.ikepolicy.name_or_id }}</a></dd>
<dt>{% trans "IPSec Policy" %}</dt>
{% url 'horizon:project:vpn:ipsecpolicydetails' ipsecsiteconnection.ipsecpolicy_id as ipsecpolicy_url %}
<dd><a href="{{ ipsecpolicy_url }}">{{ ipsecsiteconnection.ipsecpolicy.name_or_id }}</a></dd>
<dt>{% trans "Peer gateway public IPv4/IPv6 Address or FQDN" %}</dt>
<dd>{{ ipsecsiteconnection.peer_address }}</dd>
<dt>{% trans "Peer router identity for authentication (Peer ID)" %}</dt>
<dd>{{ ipsecsiteconnection.peer_id }}</dd>
<dt>{% trans "Remote peer subnet" %}</dt>
<dd>
{% for peer_cidr in ipsecsiteconnection.peer_cidrs %}
{{ peer_cidr }}<br>
{% endfor %}
</dd>
<dt>{% trans "MTU" %}</dt>
<dd>{{ ipsecsiteconnection.mtu }}</dd>
<dt>{% trans "Initiator state" %}</dt>
<dd>{{ ipsecsiteconnection.initiator }}</dd>
<dt>{% trans "Dead peer detection action" %}</dt>
<dd>{{ ipsecsiteconnection.dpd.action }}</dd>
<dt>{% trans "Dead peer detection interval" %}</dt>
<dd>{{ ipsecsiteconnection.dpd.interval }}</dd>
<dt>{% trans "Dead peer detection timeout" %}</dt>
<dd>{{ ipsecsiteconnection.dpd.timeout }}</dd>
<dt>{% trans "Authorization mode" %}</dt>
<dd>{{ ipsecsiteconnection.auth_mode }}</dd>
<dt>{% trans "Route mode" %}</dt>
<dd>{{ ipsecsiteconnection.route_mode }}</dd>
<dt>{% trans "Admin State" %}</dt>
<dd>{{ ipsecsiteconnection.admin_state_up }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ ipsecsiteconnection.status }}</dd>
</dl>
</div>

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update IKE Policy details here." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update IPSec Policy details here." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update IPSec Site Connection details here." %}</p>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends "horizon/common/_modal_form.html" %}
{% load i18n %}
{% block modal-body-right %}
<h3>{% trans "Description:" %}</h3>
<p>{% trans "You may update VPN Service details here." %}</p>
{% endblock %}

View File

@ -0,0 +1,13 @@
{% load i18n %}
{% if external_v4_ip or external_v6_ip %}
<ul>
<li>
<strong>{% trans "IPv4:" %}</strong> {{ external_v4_ip }}
</li>
<li>
<strong>{% trans "IPv6:" %}</strong> {{ external_v6_ip }}
</li>
</ul>
{% else %}
{% trans "-" %}
{% endif %}

View File

@ -0,0 +1,54 @@
{% load i18n sizeformat parse_date %}
<div class="detail">
<dl class="dl-horizontal">
<dt>{% trans "Name" %}</dt>
<dd data-display="{{ vpnservice.name_or_id }}">{{ vpnservice.name|default:_("None") }}</dd>
<dt>{% trans "Description" %}</dt>
<dd>{{ vpnservice.description|default:_("None") }}</dd>
<dt>{% trans "ID" %}</dt>
<dd>{{ vpnservice.id }}</dd>
<dt>{% trans "Project ID" %}</dt>
<dd>{{ vpnservice.tenant_id }}</dd>
<dt>{% trans "Router ID" %}</dt>
{% url 'horizon:project:routers:detail' vpnservice.router_id as router_url %}
<dd><a href="{{ router_url }}">{{ vpnservice.router.name_or_id }}</a></dd>
<dt>{% trans "Subnet ID" %}</dt>
{% url 'horizon:project:networks:subnets:detail' vpnservice.subnet_id as subnet_url %}
<dd><a href="{{ subnet_url }}">{{ vpnservice.subnet.name_or_id }} {{ vpnservice.subnet.cidr }}</a></dd>
<dt>{% trans "VPN Connections" %}</dt>
<dd>
{% if vpnservice.ipsecsiteconns %}
{% for conn in vpnservice.ipsecsiteconns %}
{% url 'horizon:project:vpn:ipsecsiteconnectiondetails' conn.id as conn_url %}
<a href="{{ conn_url }}">{{ conn.name_or_id }}</a><br>
{% endfor %}
{% else %}
None
{% endif %}
</dd>
<dt>{% trans "Admin State" %}</dt>
<dd>{{ vpnservice.admin_state_up }}</dd>
<dt>{% trans "Status" %}</dt>
<dd>{{ vpnservice.status }}</dd>
</dl>
{% if vpnservice.external_v4_ip or vpnservice.external_v6_ip %}
<h4>Local Side Public IP Addresses</h4>
<hr class="header_rule">
<dl class="dl-horizontal">
<dt>{% trans "IPv4" %}</dt>
<dd>{{ vpnservice.external_v4_ip|default:_("None") }}</dd>
<dt>{% trans "IPv6" %}</dt>
<dd>{{ vpnservice.external_v6_ip|default:_("None") }}</dd>
</dl>
{% endif %}
</div>

View File

@ -0,0 +1,11 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Virtual Private Network" %}{% endblock %}
{% block main %}
<div class="row">
<div class="col-sm-12">
{{ tab_group.render }}
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit IKE Policy" %}{% endblock %}
{% block main %}
{% include 'project/vpn/_update_ikepolicy.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit IPSec Policy" %}{% endblock %}
{% block main %}
{% include 'project/vpn/_update_ipsecpolicy.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit IPSec Site Connection" %}{% endblock %}
{% block main %}
{% include 'project/vpn/_update_ipsecsiteconnection.html' %}
{% endblock %}

View File

@ -0,0 +1,7 @@
{% extends 'base.html' %}
{% load i18n %}
{% block title %}{% trans "Edit VPN Service" %}{% endblock %}
{% block main %}
{% include 'project/vpn/_update_vpnservice.html' %}
{% endblock %}

View File

@ -0,0 +1,813 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from mox3.mox import IsA
from django.core.urlresolvers import reverse
from django import http
from horizon.workflows import views
from openstack_dashboard import api
from openstack_dashboard.test import helpers as test
from openstack_dashboard.dashboards.project.vpn import workflows
class VPNTests(test.TestCase):
class AttributeDict(dict):
def __getattr__(self, attr):
return self[attr]
def __setattr__(self, attr, value):
self[attr] = value
DASHBOARD = 'project'
INDEX_URL = reverse('horizon:%s:vpn:index' % DASHBOARD)
ADDIKEPOLICY_PATH = 'horizon:%s:vpn:addikepolicy' % DASHBOARD
ADDIPSECPOLICY_PATH = 'horizon:%s:vpn:addipsecpolicy' % DASHBOARD
ADDVPNSERVICE_PATH = 'horizon:%s:vpn:addvpnservice' % DASHBOARD
ADDVPNCONNECTION_PATH = 'horizon:%s:vpn:addipsecsiteconnection' % DASHBOARD
IKEPOLICY_DETAIL_PATH = 'horizon:%s:vpn:ikepolicydetails' % DASHBOARD
IPSECPOLICY_DETAIL_PATH = 'horizon:%s:vpn:ipsecpolicydetails' % DASHBOARD
VPNSERVICE_DETAIL_PATH = 'horizon:%s:vpn:vpnservicedetails' % DASHBOARD
VPNCONNECTION_DETAIL_PATH = 'horizon:%s:vpn:ipsecsiteconnectiondetails' %\
DASHBOARD
UPDATEIKEPOLICY_PATH = 'horizon:%s:vpn:update_ikepolicy' % DASHBOARD
UPDATEIPSECPOLICY_PATH = 'horizon:%s:vpn:update_ipsecpolicy' % DASHBOARD
UPDATEVPNSERVICE_PATH = 'horizon:%s:vpn:update_vpnservice' % DASHBOARD
UPDATEVPNCONNECTION_PATH = 'horizon:%s:vpn:update_ipsecsiteconnection' %\
DASHBOARD
def set_up_expect(self):
# retrieves vpnservices
api.vpn.vpnservice_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.vpnservices.list())
# retrieves ikepolicies
api.vpn.ikepolicy_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.ikepolicies.list())
# retrieves ipsecpolicies
api.vpn.ipsecpolicy_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.ipsecpolicies.list())
# retrieves ipsecsiteconnections
api.vpn.ipsecsiteconnection_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.ipsecsiteconnections.list())
def set_up_expect_with_exception(self):
api.vpn.vpnservice_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndRaise(self.exceptions.neutron)
api.vpn.ikepolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndRaise(self.exceptions.neutron)
api.vpn.ipsecpolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndRaise(self.exceptions.neutron)
api.vpn.ipsecsiteconnection_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndRaise(self.exceptions.neutron)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_vpnservices(self):
self.set_up_expect()
self.mox.ReplayAll()
res = self.client.get(self.INDEX_URL)
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data),
len(self.vpnservices.list()))
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_ikepolicies(self):
self.set_up_expect()
self.mox.ReplayAll()
res = self.client.get(self.INDEX_URL + '?tab=vpntabs__ikepolicies')
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['ikepoliciestable_table'].data),
len(self.ikepolicies.list()))
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_ipsecpolicies(self):
self.set_up_expect()
self.mox.ReplayAll()
res = self.client.get(self.INDEX_URL + '?tab=vpntabs__ipsecpolicies')
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['ipsecpoliciestable_table'].data),
len(self.ipsecpolicies.list()))
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_ipsecsiteconnections(self):
self.set_up_expect()
self.mox.ReplayAll()
res = self.client.get(
self.INDEX_URL + '?tab=vpntabs__ipsecsiteconnections')
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res, 'horizon/common/_detail_table.html')
self.assertEqual(
len(res.context['ipsecsiteconnectionstable_table'].data),
len(self.ipsecsiteconnections.list()))
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_exception_vpnservices(self):
self.set_up_expect_with_exception()
self.mox.ReplayAll()
res = self.client.get(self.INDEX_URL)
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res,
'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data), 0)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_exception_ikepolicies(self):
self.set_up_expect_with_exception()
self.mox.ReplayAll()
res = self.client.get(self.INDEX_URL + '?tab=vpntabs__ikepolicies')
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res,
'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data), 0)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_exception_ipsecpolicies(self):
self.set_up_expect_with_exception()
self.mox.ReplayAll()
res = self.client.get(self.INDEX_URL + '?tab=vpntabs__ipsecpolicies')
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res,
'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data), 0)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_list')})
def test_index_exception_ipsecsiteconnections(self):
self.set_up_expect_with_exception()
self.mox.ReplayAll()
res = self.client.get(
self.INDEX_URL + '?tab=vpntabs__ipsecsiteconnections')
self.assertTemplateUsed(res, '%s/vpn/index.html'
% self.DASHBOARD)
self.assertTemplateUsed(res,
'horizon/common/_detail_table.html')
self.assertEqual(len(res.context['table'].data), 0)
@test.create_stubs({api.neutron: ('network_list_for_tenant',
'router_list')})
def test_add_vpnservice_get(self):
networks = [{'subnets': [self.subnets.first(), ]}, ]
routers = self.routers.list()
api.neutron.network_list_for_tenant(
IsA(http.HttpRequest), self.tenant.id).AndReturn(networks)
api.neutron.router_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id).AndReturn(routers)
self.mox.ReplayAll()
res = self.client.get(reverse(self.ADDVPNSERVICE_PATH))
workflow = res.context['workflow']
self.assertTemplateUsed(res, views.WorkflowView.template_name)
self.assertEqual(workflow.name, workflows.AddVPNService.name)
expected_objs = ['<AddVPNServiceStep: addvpnserviceaction>', ]
self.assertQuerysetEqual(workflow.steps, expected_objs)
@test.create_stubs({api.neutron: ('router_list',
'network_list_for_tenant'),
api.vpn: ('vpnservice_create', )})
def test_add_vpnservice_post(self):
vpnservice = self.vpnservices.first()
networks = [{'subnets': [self.subnets.first(), ]}, ]
routers = self.routers.list()
api.neutron.network_list_for_tenant(
IsA(http.HttpRequest), self.tenant.id).AndReturn(networks)
api.neutron.router_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id).AndReturn(routers)
form_data = {'name': vpnservice['name'],
'description': vpnservice['description'],
'subnet_id': vpnservice['subnet_id'],
'router_id': vpnservice['router_id'],
'admin_state_up': vpnservice['admin_state_up']}
api.vpn.vpnservice_create(
IsA(http.HttpRequest), **form_data).AndReturn(vpnservice)
self.mox.ReplayAll()
res = self.client.post(reverse(self.ADDVPNSERVICE_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
@test.create_stubs({api.neutron: ('router_list',
'network_list_for_tenant')})
def test_add_vpnservice_post_error(self):
vpnservice = self.vpnservices.first()
networks = [{'subnets': [self.subnets.first(), ]}, ]
routers = self.routers.list()
api.neutron.network_list_for_tenant(
IsA(http.HttpRequest), self.tenant.id).AndReturn(networks)
api.neutron.router_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id).AndReturn(routers)
self.mox.ReplayAll()
form_data = {'name': vpnservice['name'],
'description': vpnservice['description'],
'subnet_id': '',
'router_id': '',
'admin_state_up': vpnservice['admin_state_up']}
res = self.client.post(reverse(self.ADDVPNSERVICE_PATH), form_data)
self.assertFormErrors(res, 2)
def test_add_ikepolicy_get(self):
res = self.client.get(reverse(self.ADDIKEPOLICY_PATH))
workflow = res.context['workflow']
self.assertTemplateUsed(res, views.WorkflowView.template_name)
self.assertEqual(workflow.name, workflows.AddIKEPolicy.name)
expected_objs = ['<AddIKEPolicyStep: addikepolicyaction>', ]
self.assertQuerysetEqual(workflow.steps, expected_objs)
@test.create_stubs({api.vpn: ('ikepolicy_create', )})
def test_add_ikepolicy_post(self):
ikepolicy = self.ikepolicies.first()
form_data = {'name': ikepolicy['name'],
'description': ikepolicy['description'],
'auth_algorithm': ikepolicy['auth_algorithm'],
'encryption_algorithm': ikepolicy[
'encryption_algorithm'],
'ike_version': ikepolicy['ike_version'],
'lifetime_units': ikepolicy['lifetime']['units'],
'lifetime_value': ikepolicy['lifetime']['value'],
'phase1_negotiation_mode': ikepolicy[
'phase1_negotiation_mode'],
'pfs': ikepolicy['pfs']}
api.vpn.ikepolicy_create(
IsA(http.HttpRequest), **form_data).AndReturn(ikepolicy)
self.mox.ReplayAll()
res = self.client.post(reverse(self.ADDIKEPOLICY_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
def test_add_ikepolicy_post_error(self):
ikepolicy = self.ikepolicies.first()
form_data = {'name': ikepolicy['name'],
'description': ikepolicy['description'],
'auth_algorithm': ikepolicy['auth_algorithm'],
'encryption_algorithm': ikepolicy[
'encryption_algorithm'],
'ike_version': ikepolicy['ike_version'],
'lifetime_units': ikepolicy['lifetime']['units'],
'lifetime_value': 10,
'phase1_negotiation_mode': ikepolicy[
'phase1_negotiation_mode'],
'pfs': ikepolicy['pfs']}
res = self.client.post(reverse(self.ADDIKEPOLICY_PATH), form_data)
self.assertFormErrors(res, 1)
def test_add_ipsecpolicy_get(self):
res = self.client.get(reverse(self.ADDIPSECPOLICY_PATH))
workflow = res.context['workflow']
self.assertTemplateUsed(res, views.WorkflowView.template_name)
self.assertEqual(workflow.name, workflows.AddIPSecPolicy.name)
expected_objs = ['<AddIPSecPolicyStep: addipsecpolicyaction>', ]
self.assertQuerysetEqual(workflow.steps, expected_objs)
@test.create_stubs({api.vpn: ('ipsecpolicy_create', )})
def test_add_ipsecpolicy_post(self):
ipsecpolicy = self.ipsecpolicies.first()
form_data = {'name': ipsecpolicy['name'],
'description': ipsecpolicy['description'],
'auth_algorithm': ipsecpolicy['auth_algorithm'],
'encryption_algorithm': ipsecpolicy[
'encryption_algorithm'],
'encapsulation_mode': ipsecpolicy[
'encapsulation_mode'],
'lifetime_units': ipsecpolicy['lifetime']['units'],
'lifetime_value': ipsecpolicy['lifetime']['value'],
'pfs': ipsecpolicy['pfs'],
'transform_protocol': ipsecpolicy[
'transform_protocol']}
api.vpn.ipsecpolicy_create(
IsA(http.HttpRequest), **form_data).AndReturn(ipsecpolicy)
self.mox.ReplayAll()
res = self.client.post(reverse(self.ADDIPSECPOLICY_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
def test_add_ipsecpolicy_post_error(self):
ipsecpolicy = self.ipsecpolicies.first()
form_data = {'name': ipsecpolicy['name'],
'description': ipsecpolicy['description'],
'auth_algorithm': ipsecpolicy['auth_algorithm'],
'encryption_algorithm': ipsecpolicy[
'encryption_algorithm'],
'encapsulation_mode': ipsecpolicy[
'encapsulation_mode'],
'lifetime_units': ipsecpolicy['lifetime']['units'],
'lifetime_value': 10,
'pfs': ipsecpolicy['pfs'],
'transform_protocol': ipsecpolicy[
'transform_protocol']}
res = self.client.post(reverse(self.ADDIPSECPOLICY_PATH), form_data)
self.assertFormErrors(res, 1)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list')})
def test_add_ipsecsiteconnection_get(self):
ikepolicies = self.ikepolicies.list()
ipsecpolicies = self.ipsecpolicies.list()
vpnservices = self.vpnservices.list()
api.vpn.ikepolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(ikepolicies)
api.vpn.ipsecpolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(ipsecpolicies)
api.vpn.vpnservice_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(vpnservices)
self.mox.ReplayAll()
res = self.client.get(reverse(self.ADDVPNCONNECTION_PATH))
workflow = res.context['workflow']
self.assertTemplateUsed(res, views.WorkflowView.template_name)
self.assertEqual(workflow.name, workflows.AddIPSecSiteConnection.name)
expected_objs = ['<AddIPSecSiteConnectionStep: '
'addipsecsiteconnectionaction>',
'<AddIPSecSiteConnectionOptionalStep: '
'addipsecsiteconnectionoptionalaction>', ]
self.assertQuerysetEqual(workflow.steps, expected_objs)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_create')})
def test_add_ipsecsiteconnection_post(self):
self._test_add_ipsecsiteconnection_post()
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_create')})
def test_add_ipsecsiteconnection_post_single_subnet(self):
self._test_add_ipsecsiteconnection_post(subnet_list=False)
def _test_add_ipsecsiteconnection_post(self, subnet_list=True):
if subnet_list:
ipsecsiteconnection = self.ipsecsiteconnections.first()
else:
ipsecsiteconnection = self.ipsecsiteconnections.list()[1]
ikepolicies = self.ikepolicies.list()
ipsecpolicies = self.ipsecpolicies.list()
vpnservices = self.vpnservices.list()
api.vpn.ikepolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(ikepolicies)
api.vpn.ipsecpolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(ipsecpolicies)
api.vpn.vpnservice_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(vpnservices)
form_data = {'name': ipsecsiteconnection['name'],
'description': ipsecsiteconnection['description'],
'dpd_action': ipsecsiteconnection['dpd']['action'],
'dpd_interval': ipsecsiteconnection['dpd']['interval'],
'dpd_timeout': ipsecsiteconnection['dpd']['timeout'],
'ikepolicy_id': ipsecsiteconnection['ikepolicy_id'],
'initiator': ipsecsiteconnection['initiator'],
'ipsecpolicy_id': ipsecsiteconnection[
'ipsecpolicy_id'],
'mtu': ipsecsiteconnection['mtu'],
'peer_address': ipsecsiteconnection['peer_address'],
'peer_cidrs': ipsecsiteconnection['peer_cidrs'],
'peer_id': ipsecsiteconnection['peer_id'],
'psk': ipsecsiteconnection['psk'],
'vpnservice_id': ipsecsiteconnection['vpnservice_id'],
'admin_state_up': ipsecsiteconnection[
'admin_state_up']}
api.vpn.ipsecsiteconnection_create(
IsA(http.HttpRequest), **form_data).AndReturn(ipsecsiteconnection)
self.mox.ReplayAll()
res = self.client.post(reverse(self.ADDVPNCONNECTION_PATH), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_create')})
def test_add_ipsecsiteconnection_post_required_fields_error(self):
self._test_add_ipsecsiteconnection_post_error()
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ipsecpolicy_list',
'vpnservice_list',
'ipsecsiteconnection_create')})
def test_add_ipsecsiteconnection_post_peer_cidrs_error(self):
self._test_add_ipsecsiteconnection_post_error(subnets=True)
def _test_add_ipsecsiteconnection_post_error(self, subnets=False):
ipsecsiteconnection = self.ipsecsiteconnections.first()
ikepolicies = self.ikepolicies.list()
ipsecpolicies = self.ipsecpolicies.list()
vpnservices = self.vpnservices.list()
api.vpn.ikepolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(ikepolicies)
api.vpn.ipsecpolicy_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(ipsecpolicies)
api.vpn.vpnservice_list(
IsA(http.HttpRequest),
tenant_id=self.tenant.id).AndReturn(vpnservices)
self.mox.ReplayAll()
form_data = {'name': '',
'description': ipsecsiteconnection['description'],
'dpd_action': ipsecsiteconnection['dpd']['action'],
'dpd_interval': ipsecsiteconnection['dpd']['interval'],
'dpd_timeout': ipsecsiteconnection['dpd']['timeout'],
'ikepolicy_id': '',
'initiator': ipsecsiteconnection['initiator'],
'ipsecpolicy_id': '',
'mtu': ipsecsiteconnection['mtu'],
'peer_address': '',
'peer_cidrs': '',
'peer_id': '',
'psk': '',
'vpnservice_id': '',
'admin_state_up': ipsecsiteconnection[
'admin_state_up']}
if subnets:
form_data['peer_cidrs'] = '20.1.0.0/24; 21.1.0.0/24'
res = self.client.post(reverse(self.ADDVPNCONNECTION_PATH), form_data)
self.assertFormErrors(res, 7)
@test.create_stubs({api.vpn: ('vpnservice_get', )})
def test_update_vpnservice_get(self):
vpnservice = self.vpnservices.first()
api.vpn.vpnservice_get(IsA(http.HttpRequest), vpnservice.id)\
.AndReturn(vpnservice)
self.mox.ReplayAll()
res = self.client.get(
reverse(self.UPDATEVPNSERVICE_PATH, args=(vpnservice.id,)))
self.assertTemplateUsed(
res, 'project/vpn/update_vpnservice.html')
@test.create_stubs({api.vpn: ('vpnservice_get', 'vpnservice_update')})
def test_update_vpnservice_post(self):
vpnservice = self.vpnservices.first()
api.vpn.vpnservice_get(IsA(http.HttpRequest), vpnservice.id)\
.AndReturn(vpnservice)
data = {'name': vpnservice.name,
'description': vpnservice.description,
'admin_state_up': vpnservice.admin_state_up}
api.vpn.vpnservice_update(IsA(http.HttpRequest), vpnservice.id,
vpnservice=data).AndReturn(vpnservice)
self.mox.ReplayAll()
form_data = data.copy()
form_data['vpnservice_id'] = vpnservice.id
res = self.client.post(reverse(
self.UPDATEVPNSERVICE_PATH, args=(vpnservice.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
@test.create_stubs({api.vpn: ('ikepolicy_get', )})
def test_update_ikepolicy_get(self):
ikepolicy = self.ikepolicies.first()
api.vpn.ikepolicy_get(IsA(http.HttpRequest), ikepolicy.id)\
.AndReturn(ikepolicy)
self.mox.ReplayAll()
res = self.client.get(
reverse(self.UPDATEIKEPOLICY_PATH, args=(ikepolicy.id,)))
self.assertTemplateUsed(
res, 'project/vpn/update_ikepolicy.html')
@test.create_stubs({api.vpn: ('ikepolicy_get', 'ikepolicy_update')})
def test_update_ikepolicy_post(self):
ikepolicy = self.ikepolicies.first()
api.vpn.ikepolicy_get(IsA(http.HttpRequest), ikepolicy.id)\
.AndReturn(ikepolicy)
data = {'name': ikepolicy.name,
'description': ikepolicy.description,
'auth_algorithm': ikepolicy.auth_algorithm,
'encryption_algorithm': ikepolicy.encryption_algorithm,
'ike_version': ikepolicy.ike_version,
'lifetime': ikepolicy.lifetime,
'pfs': ikepolicy.pfs,
'phase1_negotiation_mode': ikepolicy.phase1_negotiation_mode}
api.vpn.ikepolicy_update(IsA(http.HttpRequest), ikepolicy.id,
ikepolicy=data).AndReturn(ikepolicy)
self.mox.ReplayAll()
form_data = data.copy()
form_data.update({'lifetime_units': form_data['lifetime']['units'],
'lifetime_value': form_data['lifetime']['value'],
'ikepolicy_id': ikepolicy.id})
form_data.pop('lifetime')
res = self.client.post(reverse(
self.UPDATEIKEPOLICY_PATH, args=(ikepolicy.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
@test.create_stubs({api.vpn: ('ipsecpolicy_get', )})
def test_update_ipsecpolicy_get(self):
ipsecpolicy = self.ipsecpolicies.first()
api.vpn.ipsecpolicy_get(IsA(http.HttpRequest), ipsecpolicy.id)\
.AndReturn(ipsecpolicy)
self.mox.ReplayAll()
res = self.client.get(
reverse(self.UPDATEIPSECPOLICY_PATH, args=(ipsecpolicy.id,)))
self.assertTemplateUsed(
res, 'project/vpn/update_ipsecpolicy.html')
@test.create_stubs({api.vpn: ('ipsecpolicy_get', 'ipsecpolicy_update')})
def test_update_ipsecpolicy_post(self):
ipsecpolicy = self.ipsecpolicies.first()
api.vpn.ipsecpolicy_get(IsA(http.HttpRequest), ipsecpolicy.id)\
.AndReturn(ipsecpolicy)
data = {'name': ipsecpolicy.name,
'description': ipsecpolicy.description,
'auth_algorithm': ipsecpolicy.auth_algorithm,
'encapsulation_mode': ipsecpolicy.encapsulation_mode,
'encryption_algorithm': ipsecpolicy.encryption_algorithm,
'lifetime': ipsecpolicy.lifetime,
'pfs': ipsecpolicy.pfs,
'transform_protocol': ipsecpolicy.transform_protocol}
api.vpn.ipsecpolicy_update(IsA(http.HttpRequest), ipsecpolicy.id,
ipsecpolicy=data).AndReturn(ipsecpolicy)
self.mox.ReplayAll()
form_data = data.copy()
form_data.update({'lifetime_units': form_data['lifetime']['units'],
'lifetime_value': form_data['lifetime']['value'],
'ipsecpolicy_id': ipsecpolicy.id})
form_data.pop('lifetime')
res = self.client.post(reverse(
self.UPDATEIPSECPOLICY_PATH, args=(ipsecpolicy.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
@test.create_stubs({api.vpn: ('ipsecsiteconnection_get', )})
def test_update_ipsecsiteconnection_get(self):
ipsecsiteconnection = self.ipsecsiteconnections.first()
api.vpn.ipsecsiteconnection_get(
IsA(http.HttpRequest), ipsecsiteconnection.id)\
.AndReturn(ipsecsiteconnection)
self.mox.ReplayAll()
res = self.client.get(
reverse(self.UPDATEVPNCONNECTION_PATH,
args=(ipsecsiteconnection.id,)))
self.assertTemplateUsed(
res, 'project/vpn/update_ipsecsiteconnection.html')
@test.create_stubs({api.vpn: ('ipsecsiteconnection_get',
'ipsecsiteconnection_update')})
def test_update_ipsecsiteconnection_post(self):
ipsecsiteconnection = self.ipsecsiteconnections.first()
api.vpn.ipsecsiteconnection_get(
IsA(http.HttpRequest), ipsecsiteconnection.id)\
.AndReturn(ipsecsiteconnection)
data = {'name': ipsecsiteconnection.name,
'description': ipsecsiteconnection.description,
'peer_address': ipsecsiteconnection.peer_address,
'peer_id': ipsecsiteconnection.peer_id,
'peer_cidrs': ipsecsiteconnection.peer_cidrs,
'psk': ipsecsiteconnection.psk,
'mtu': ipsecsiteconnection.mtu,
'dpd': ipsecsiteconnection.dpd,
'initiator': ipsecsiteconnection.initiator,
'admin_state_up': ipsecsiteconnection.admin_state_up}
api.vpn.ipsecsiteconnection_update(
IsA(http.HttpRequest), ipsecsiteconnection.id,
ipsec_site_connection=data).AndReturn(ipsecsiteconnection)
self.mox.ReplayAll()
form_data = data.copy()
form_data.update({
'dpd_action': form_data['dpd']['action'],
'dpd_interval': form_data['dpd']['interval'],
'dpd_timeout': form_data['dpd']['timeout'],
'peer_cidrs': ", ".join(ipsecsiteconnection['peer_cidrs']),
'ipsecsiteconnection_id': ipsecsiteconnection.id,
})
form_data.pop('dpd')
res = self.client.post(
reverse(self.UPDATEVPNCONNECTION_PATH,
args=(ipsecsiteconnection.id,)), form_data)
self.assertNoFormErrors(res)
self.assertRedirectsNoFollow(res, str(self.INDEX_URL))
@test.create_stubs({api.vpn: ('vpnservice_list', 'vpnservice_delete',)})
def test_delete_vpnservice(self):
vpnservice = self.vpnservices.list()[1]
api.vpn.vpnservice_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.vpnservices.list())
api.vpn.vpnservice_delete(IsA(http.HttpRequest), vpnservice.id)
self.mox.ReplayAll()
form_data = {"action":
"vpnservicestable__deletevpnservice__%s" % vpnservice.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)
@test.create_stubs({api.vpn: ('ikepolicy_list', 'ikepolicy_delete',)})
def test_delete_ikepolicy(self):
ikepolicy = self.ikepolicies.list()[1]
api.vpn.ikepolicy_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.ikepolicies.list())
api.vpn.ikepolicy_delete(IsA(http.HttpRequest), ikepolicy.id)
self.mox.ReplayAll()
form_data = {"action":
"ikepoliciestable__deleteikepolicy__%s" % ikepolicy.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)
@test.create_stubs({api.vpn: ('ipsecpolicy_list', 'ipsecpolicy_delete',)})
def test_delete_ipsecpolicy(self):
ipsecpolicy = self.ipsecpolicies.list()[1]
api.vpn.ipsecpolicy_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.ipsecpolicies.list())
api.vpn.ipsecpolicy_delete(IsA(http.HttpRequest), ipsecpolicy.id)
self.mox.ReplayAll()
form_data = {"action":
"ipsecpoliciestable__deleteipsecpolicy__%s"
% ipsecpolicy.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)
@test.create_stubs({api.vpn: ('ipsecsiteconnection_list',
'ipsecsiteconnection_delete',)})
def test_delete_ipsecsiteconnection(self):
ipsecsiteconnection = self.ipsecsiteconnections.first()
api.vpn.ipsecsiteconnection_list(
IsA(http.HttpRequest), tenant_id=self.tenant.id) \
.AndReturn(self.ipsecsiteconnections.list())
api.vpn.ipsecsiteconnection_delete(
IsA(http.HttpRequest), ipsecsiteconnection.id)
self.mox.ReplayAll()
form_data = {"action":
"ipsecsiteconnectionstable__deleteipsecsiteconnection__%s"
% ipsecsiteconnection.id}
res = self.client.post(self.INDEX_URL, form_data)
self.assertNoFormErrors(res)

View File

@ -0,0 +1,48 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from django.conf.urls import url
from neutron_vpnaas_dashboard.dashboards.project import views
urlpatterns = [
url(r'^$', views.IndexView.as_view(), name='index'),
url(r'^addikepolicy$',
views.AddIKEPolicyView.as_view(), name='addikepolicy'),
url(r'^update_ikepolicy/(?P<ikepolicy_id>[^/]+)/$',
views.UpdateIKEPolicyView.as_view(), name='update_ikepolicy'),
url(r'^addipsecpolicy$',
views.AddIPSecPolicyView.as_view(), name='addipsecpolicy'),
url(r'^update_ipsecpolicy/(?P<ipsecpolicy_id>[^/]+)/$',
views.UpdateIPSecPolicyView.as_view(), name='update_ipsecpolicy'),
url(r'^addipsecsiteconnection$',
views.AddIPSecSiteConnectionView.as_view(),
name='addipsecsiteconnection'),
url(r'^update_ipsecsiteconnection/(?P<ipsecsiteconnection_id>[^/]+)/$',
views.UpdateIPSecSiteConnectionView.as_view(),
name='update_ipsecsiteconnection'),
url(r'^addvpnservice$',
views.AddVPNServiceView.as_view(), name='addvpnservice'),
url(r'^update_vpnservice/(?P<vpnservice_id>[^/]+)/$',
views.UpdateVPNServiceView.as_view(), name='update_vpnservice'),
url(r'^ikepolicy/(?P<ikepolicy_id>[^/]+)/$',
views.IKEPolicyDetailsView.as_view(), name='ikepolicydetails'),
url(r'^ipsecpolicy/(?P<ipsecpolicy_id>[^/]+)/$',
views.IPSecPolicyDetailsView.as_view(), name='ipsecpolicydetails'),
url(r'^vpnservice/(?P<vpnservice_id>[^/]+)/$',
views.VPNServiceDetailsView.as_view(), name='vpnservicedetails'),
url(r'^ipsecsiteconnection/(?P<ipsecsiteconnection_id>[^/]+)/$',
views.IPSecSiteConnectionDetailsView.as_view(),
name='ipsecsiteconnectiondetails'),
]

View File

@ -0,0 +1,361 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from django.core.urlresolvers import reverse
from django.core.urlresolvers import reverse_lazy
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import tabs
from horizon.utils import memoized
from horizon import workflows
from neutron_vpnaas_dashboard import api as api_vpn
from neutron_vpnaas_dashboard.dashboards.project import forms as vpn_forms
from neutron_vpnaas_dashboard.dashboards.project import tables as vpn_tables
from neutron_vpnaas_dashboard.dashboards.project import tabs as vpn_tabs
from neutron_vpnaas_dashboard.dashboards.project import workflows as vpn_workflows
class IndexView(tabs.TabbedTableView):
tab_group_class = vpn_tabs.VPNTabs
template_name = 'project/vpn/index.html'
page_title = _("Virtual Private Network")
class AddVPNServiceView(workflows.WorkflowView):
workflow_class = vpn_workflows.AddVPNService
class AddIPSecSiteConnectionView(workflows.WorkflowView):
workflow_class = vpn_workflows.AddIPSecSiteConnection
class AddIKEPolicyView(workflows.WorkflowView):
workflow_class = vpn_workflows.AddIKEPolicy
class AddIPSecPolicyView(workflows.WorkflowView):
workflow_class = vpn_workflows.AddIPSecPolicy
class IKEPolicyDetailsView(tabs.TabView):
tab_group_class = vpn_tabs.IKEPolicyDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ ikepolicy.name|default:ikepolicy.id }}"
@memoized.memoized_method
def get_data(self):
pid = self.kwargs['ikepolicy_id']
try:
return api_vpn.ikepolicy_get(self.request, pid)
except Exception:
msg = _('Unable to retrieve IKE Policy details.')
exceptions.handle(self.request, msg,
redirect=self.get_redirect_url())
def get_context_data(self, **kwargs):
context = super(IKEPolicyDetailsView, self).get_context_data(**kwargs)
ikepolicy = self.get_data()
table = vpn_tables.IKEPoliciesTable(self.request)
context["ikepolicy"] = ikepolicy
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(ikepolicy)
return context
def get_tabs(self, request, *args, **kwargs):
ikepolicy = self.get_data()
return self.tab_group_class(request, ikepolicy=ikepolicy, **kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy('horizon:project:vpn:index')
class IPSecPolicyDetailsView(tabs.TabView):
tab_group_class = vpn_tabs.IPSecPolicyDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ ipsecpolicy.name|default:ipsecpolicy.id }}"
@memoized.memoized_method
def get_data(self):
pid = self.kwargs['ipsecpolicy_id']
try:
return api_vpn.ipsecpolicy_get(self.request, pid)
except Exception:
msg = _('Unable to retrieve IPSec Policy details.')
exceptions.handle(self.request, msg,
redirect=self.get_redirect_url())
def get_context_data(self, **kwargs):
context = super(IPSecPolicyDetailsView, self).get_context_data(
**kwargs)
ipsecpolicy = self.get_data()
table = vpn_tables.IPSecPoliciesTable(self.request)
context["ipsecpolicy"] = ipsecpolicy
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(ipsecpolicy)
return context
def get_tabs(self, request, *args, **kwargs):
ipsecpolicy = self.get_data()
return self.tab_group_class(request, ipsecpolicy=ipsecpolicy, **kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy('horizon:project:vpn:index')
class VPNServiceDetailsView(tabs.TabView):
tab_group_class = vpn_tabs.VPNServiceDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ vpnservice.name|default:vpnservice.id }}"
@memoized.memoized_method
def get_data(self):
sid = self.kwargs['vpnservice_id']
try:
vpnservice = api_vpn.vpnservice_get(self.request, sid)
except Exception:
vpnservice = []
msg = _('Unable to retrieve VPN Service details.')
exceptions.handle(self.request, msg,
redirect=self.get_redirect_url())
try:
connections = api_vpn.ipsecsiteconnection_list(
self.request, vpnservice_id=sid)
vpnservice.vpnconnections = connections
except Exception:
vpnservice.vpnconnections = []
return vpnservice
def get_context_data(self, **kwargs):
context = super(VPNServiceDetailsView, self).get_context_data(**kwargs)
vpnservice = self.get_data()
table = vpn_tables.VPNServicesTable(self.request)
context["vpnservice"] = vpnservice
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(vpnservice)
return context
def get_tabs(self, request, *args, **kwargs):
vpnservice = self.get_data()
return self.tab_group_class(request, vpnservice=vpnservice, **kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy('horizon:project:vpn:index')
class IPSecSiteConnectionDetailsView(tabs.TabView):
tab_group_class = vpn_tabs.IPSecSiteConnectionDetailsTabs
template_name = 'horizon/common/_detail.html'
page_title = "{{ ipsecsiteconnection.name|default:ipsecsiteconnection.id}}"
@memoized.memoized_method
def get_data(self):
cid = self.kwargs['ipsecsiteconnection_id']
try:
return api_vpn.ipsecsiteconnection_get(self.request, cid)
except Exception:
msg = _('Unable to retrieve IPSec Site Connection details.')
exceptions.handle(self.request, msg,
redirect=self.get_redirect_url())
def get_context_data(self, **kwargs):
context = super(IPSecSiteConnectionDetailsView, self).get_context_data(
**kwargs)
ipsecsiteconnection = self.get_data()
table = vpn_tables.IPSecSiteConnectionsTable(self.request)
context["ipsecsiteconnection"] = ipsecsiteconnection
context["url"] = self.get_redirect_url()
context["actions"] = table.render_row_actions(ipsecsiteconnection)
return context
def get_tabs(self, request, *args, **kwargs):
ipsecsiteconnection = self.get_data()
return self.tab_group_class(request,
ipsecsiteconnection=ipsecsiteconnection,
**kwargs)
@staticmethod
def get_redirect_url():
return reverse_lazy('horizon:project:vpn:index')
class UpdateVPNServiceView(forms.ModalFormView):
form_class = vpn_forms.UpdateVPNService
form_id = "update_vpnservice_form"
template_name = "project/vpn/update_vpnservice.html"
context_object_name = 'vpnservice'
submit_label = _("Save Changes")
submit_url = "horizon:project:vpn:update_vpnservice"
success_url = reverse_lazy("horizon:project:vpn:index")
page_title = _("Edit VPN Service")
def get_context_data(self, **kwargs):
context = super(UpdateVPNServiceView, self).get_context_data(**kwargs)
context["vpnservice_id"] = self.kwargs['vpnservice_id']
args = (self.kwargs['vpnservice_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
vpnservice_id = self.kwargs['vpnservice_id']
try:
return api_vpn.vpnservice_get(self.request, vpnservice_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve VPN Service details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
vpnservice = self._get_object()
return {'name': vpnservice['name'],
'vpnservice_id': vpnservice['id'],
'description': vpnservice['description'],
'admin_state_up': vpnservice['admin_state_up']}
class UpdateIKEPolicyView(forms.ModalFormView):
form_class = vpn_forms.UpdateIKEPolicy
form_id = "update_ikepolicy_form"
template_name = "project/vpn/update_ikepolicy.html"
context_object_name = 'ikepolicy'
submit_label = _("Save Changes")
submit_url = "horizon:project:vpn:update_ikepolicy"
success_url = reverse_lazy("horizon:project:vpn:index")
page_title = _("Edit IKE Policy")
def get_context_data(self, **kwargs):
context = super(UpdateIKEPolicyView, self).get_context_data(**kwargs)
context["ikepolicy_id"] = self.kwargs['ikepolicy_id']
args = (self.kwargs['ikepolicy_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
ikepolicy_id = self.kwargs['ikepolicy_id']
try:
return api_vpn.ikepolicy_get(self.request, ikepolicy_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve IKE Policy details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
ikepolicy = self._get_object()
return {'name': ikepolicy['name'],
'ikepolicy_id': ikepolicy['id'],
'description': ikepolicy['description'],
'auth_algorithm': ikepolicy['auth_algorithm'],
'encryption_algorithm': ikepolicy['encryption_algorithm'],
'ike_version': ikepolicy['ike_version'],
'lifetime_units': ikepolicy['lifetime']['units'],
'lifetime_value': ikepolicy['lifetime']['value'],
'pfs': ikepolicy['pfs'],
'phase1_negotiation_mode': ikepolicy[
'phase1_negotiation_mode']}
class UpdateIPSecPolicyView(forms.ModalFormView):
form_class = vpn_forms.UpdateIPSecPolicy
form_id = "update_ipsecpolicy_form"
template_name = "project/vpn/update_ipsecpolicy.html"
context_object_name = 'ipsecpolicy'
submit_label = _("Save Changes")
submit_url = "horizon:project:vpn:update_ipsecpolicy"
success_url = reverse_lazy("horizon:project:vpn:index")
page_title = _("Edit IPSec Policy")
def get_context_data(self, **kwargs):
context = super(UpdateIPSecPolicyView, self).get_context_data(**kwargs)
context["ipsecpolicy_id"] = self.kwargs['ipsecpolicy_id']
args = (self.kwargs['ipsecpolicy_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
ipsecpolicy_id = self.kwargs['ipsecpolicy_id']
try:
return api_vpn.ipsecpolicy_get(self.request, ipsecpolicy_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve IPSec Policy details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
ipsecpolicy = self._get_object()
return {'name': ipsecpolicy['name'],
'ipsecpolicy_id': ipsecpolicy['id'],
'description': ipsecpolicy['description'],
'auth_algorithm': ipsecpolicy['auth_algorithm'],
'encapsulation_mode': ipsecpolicy['encapsulation_mode'],
'encryption_algorithm': ipsecpolicy['encryption_algorithm'],
'lifetime_units': ipsecpolicy['lifetime']['units'],
'lifetime_value': ipsecpolicy['lifetime']['value'],
'pfs': ipsecpolicy['pfs'],
'transform_protocol': ipsecpolicy['transform_protocol']}
class UpdateIPSecSiteConnectionView(forms.ModalFormView):
form_class = vpn_forms.UpdateIPSecSiteConnection
form_id = "update_ipsecsiteconnection_form"
template_name = "project/vpn/update_ipsecsiteconnection.html"
context_object_name = 'ipsecsiteconnection'
submit_label = _("Save Changes")
submit_url = "horizon:project:vpn:update_ipsecsiteconnection"
success_url = reverse_lazy("horizon:project:vpn:index")
page_title = _("Edit IPSec Site Connection")
def get_context_data(self, **kwargs):
context = super(
UpdateIPSecSiteConnectionView, self).get_context_data(**kwargs)
context["ipsecsiteconnection_id"] = self.kwargs[
'ipsecsiteconnection_id']
args = (self.kwargs['ipsecsiteconnection_id'],)
context['submit_url'] = reverse(self.submit_url, args=args)
return context
@memoized.memoized_method
def _get_object(self, *args, **kwargs):
connection_id = self.kwargs['ipsecsiteconnection_id']
try:
return api_vpn.ipsecsiteconnection_get(self.request, connection_id)
except Exception as e:
redirect = self.success_url
msg = _('Unable to retrieve IPSec Site Connection details. %s') % e
exceptions.handle(self.request, msg, redirect=redirect)
def get_initial(self):
ipsecsiteconnection = self._get_object()
return {'name': ipsecsiteconnection['name'],
'ipsecsiteconnection_id': ipsecsiteconnection['id'],
'description': ipsecsiteconnection['description'],
'peer_address': ipsecsiteconnection['peer_address'],
'peer_id': ipsecsiteconnection['peer_id'],
'peer_cidrs': ", ".join(ipsecsiteconnection['peer_cidrs']),
'psk': ipsecsiteconnection['psk'],
'mtu': ipsecsiteconnection['mtu'],
'dpd_action': ipsecsiteconnection['dpd']['action'],
'dpd_interval': ipsecsiteconnection['dpd']['interval'],
'dpd_timeout': ipsecsiteconnection['dpd']['timeout'],
'initiator': ipsecsiteconnection['initiator'],
'admin_state_up': ipsecsiteconnection['admin_state_up']}

View File

@ -0,0 +1,516 @@
# Copyright 2013, Mirantis Inc
#
# 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.
from django.utils.translation import ugettext_lazy as _
from horizon import exceptions
from horizon import forms
from horizon import workflows
from openstack_dashboard import api
from neutron_vpnaas_dashboard import api as api_vpn
class AddVPNServiceAction(workflows.Action):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
description = forms.CharField(
initial="", required=False,
max_length=80, label=_("Description"))
router_id = forms.ChoiceField(label=_("Router"))
subnet_id = forms.ChoiceField(label=_("Subnet"))
admin_state_up = forms.BooleanField(
label=_("Enable Admin State"),
help_text=_("The state of VPN service to start in. If disabled "
"(not checked), VPN service does not forward packets."),
initial=True,
required=False)
def __init__(self, request, *args, **kwargs):
super(AddVPNServiceAction, self).__init__(request, *args, **kwargs)
def populate_subnet_id_choices(self, request, context):
subnet_id_choices = [('', _("Select a Subnet"))]
try:
tenant_id = request.user.tenant_id
networks = api.neutron.network_list_for_tenant(request, tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve networks list.'))
networks = []
for n in networks:
for s in n['subnets']:
subnet_id_choices.append((s.id, s.cidr))
self.fields['subnet_id'].choices = subnet_id_choices
return subnet_id_choices
def populate_router_id_choices(self, request, context):
router_id_choices = [('', _("Select a Router"))]
try:
tenant_id = request.user.tenant_id
routers = api.neutron.router_list(request, tenant_id=tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve routers list.'))
routers = []
for r in routers:
router_id_choices.append((r.id, r.name))
self.fields['router_id'].choices = router_id_choices
return router_id_choices
class Meta(object):
name = _("Add New VPN Service")
permissions = ('openstack.services.network',)
help_text_template = "project/vpn/_add_vpn_service_help.html"
class AddVPNServiceStep(workflows.Step):
action_class = AddVPNServiceAction
contributes = ("name", "description", "subnet_id",
"router_id", "admin_state_up")
def contribute(self, data, context):
context = super(AddVPNServiceStep, self).contribute(data, context)
if data:
return context
class AddVPNService(workflows.Workflow):
slug = "addvpnservice"
name = _("Add VPN Service")
finalize_button_name = _("Add")
success_message = _('Added VPN Service "%s".')
failure_message = _('Unable to add VPN Service "%s".')
success_url = "horizon:project:vpn:index"
default_steps = (AddVPNServiceStep,)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_vpn.vpnservice_create(request, **context)
return True
except Exception:
return False
class AddIKEPolicyAction(workflows.Action):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
description = forms.CharField(
initial="", required=False,
max_length=80, label=_("Description"))
auth_algorithm = forms.ChoiceField(label=_("Authorization algorithm"),
required=False)
encryption_algorithm = forms.ChoiceField(label=_("Encryption algorithm"),
required=False)
ike_version = forms.ChoiceField(label=_("IKE version"), required=False)
lifetime_units = forms.ChoiceField(label=_("Lifetime units for IKE keys"),
required=False)
lifetime_value = forms.IntegerField(
min_value=60, label=_("Lifetime value for IKE keys"),
initial=3600,
help_text=_("Equal to or greater than 60"),
required=False)
pfs = forms.ChoiceField(label=_("Perfect Forward Secrecy"), required=False)
phase1_negotiation_mode = forms.ChoiceField(
label=_("IKE Phase1 negotiation mode"), required=False)
def __init__(self, request, *args, **kwargs):
super(AddIKEPolicyAction, self).__init__(request, *args, **kwargs)
auth_algorithm_choices = [("sha1", "sha1")]
self.fields['auth_algorithm'].choices = auth_algorithm_choices
# Currently this field has only one choice, so mark it as readonly.
self.fields['auth_algorithm'].widget.attrs['readonly'] = True
encryption_algorithm_choices = [("3des", "3des"),
("aes-128", "aes-128"),
("aes-192", "aes-192"),
("aes-256", "aes-256")]
self.fields[
'encryption_algorithm'].choices = encryption_algorithm_choices
self.fields['encryption_algorithm'].initial = "aes-128"
ike_version_choices = [("v1", "v1"),
("v2", "v2")]
self.fields['ike_version'].choices = ike_version_choices
lifetime_units_choices = [("seconds", "seconds")]
self.fields['lifetime_units'].choices = lifetime_units_choices
# Currently this field has only one choice, so mark it as readonly.
self.fields['lifetime_units'].widget.attrs['readonly'] = True
pfs_choices = [("group2", "group2"),
("group5", "group5"),
("group14", "group14")]
self.fields['pfs'].choices = pfs_choices
self.fields['pfs'].initial = "group5"
phase1_neg_mode_choices = [("main", "main")]
self.fields[
'phase1_negotiation_mode'].choices = phase1_neg_mode_choices
# Currently this field has only one choice, so mark it as readonly.
self.fields['phase1_negotiation_mode'].widget.attrs['readonly'] = True
class Meta(object):
name = _("Add New IKE Policy")
permissions = ('openstack.services.network',)
help_text_template = "project/vpn/_add_ike_policy_help.html"
class AddIKEPolicyStep(workflows.Step):
action_class = AddIKEPolicyAction
contributes = ("name", "description", "auth_algorithm",
"encryption_algorithm", "ike_version",
"lifetime_units", "lifetime_value",
"pfs", "phase1_negotiation_mode")
def contribute(self, data, context):
context = super(AddIKEPolicyStep, self).contribute(data, context)
context['lifetime'] = {'units': data['lifetime_units'],
'value': data['lifetime_value']}
context.pop('lifetime_units')
context.pop('lifetime_value')
if data:
return context
class AddIKEPolicy(workflows.Workflow):
slug = "addikepolicy"
name = _("Add IKE Policy")
finalize_button_name = _("Add")
success_message = _('Added IKE Policy "%s".')
failure_message = _('Unable to add IKE Policy "%s".')
success_url = "horizon:project:vpn:index"
default_steps = (AddIKEPolicyStep,)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_vpn.ikepolicy_create(request, **context)
return True
except Exception:
return False
class AddIPSecPolicyAction(workflows.Action):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
description = forms.CharField(
initial="", required=False,
max_length=80, label=_("Description"))
auth_algorithm = forms.ChoiceField(label=_("Authorization algorithm"),
required=False)
encapsulation_mode = forms.ChoiceField(label=_("Encapsulation mode"),
required=False)
encryption_algorithm = forms.ChoiceField(label=_("Encryption algorithm"),
required=False)
lifetime_units = forms.ChoiceField(label=_("Lifetime units"),
required=False)
lifetime_value = forms.IntegerField(
min_value=60, label=_("Lifetime value for IKE keys "),
initial=3600,
help_text=_("Equal to or greater than 60"),
required=False)
pfs = forms.ChoiceField(label=_("Perfect Forward Secrecy"), required=False)
transform_protocol = forms.ChoiceField(label=_("Transform Protocol"),
required=False)
def __init__(self, request, *args, **kwargs):
super(AddIPSecPolicyAction, self).__init__(request, *args, **kwargs)
auth_algorithm_choices = [("sha1", "sha1")]
self.fields['auth_algorithm'].choices = auth_algorithm_choices
# Currently this field has only one choice, so mark it as readonly.
self.fields['auth_algorithm'].widget.attrs['readonly'] = True
encapsulation_mode_choices = [("tunnel", "tunnel"),
("transport", "transport")]
self.fields['encapsulation_mode'].choices = encapsulation_mode_choices
encryption_algorithm_choices = [("3des", "3des"),
("aes-128", "aes-128"),
("aes-192", "aes-192"),
("aes-256", "aes-256")]
self.fields[
'encryption_algorithm'].choices = encryption_algorithm_choices
self.fields['encryption_algorithm'].initial = "aes-128"
lifetime_units_choices = [("seconds", "seconds")]
self.fields['lifetime_units'].choices = lifetime_units_choices
# Currently this field has only one choice, so mark it as readonly.
self.fields['lifetime_units'].widget.attrs['readonly'] = True
pfs_choices = [("group2", "group2"),
("group5", "group5"),
("group14", "group14")]
self.fields['pfs'].choices = pfs_choices
self.fields['pfs'].initial = "group5"
transform_protocol_choices = [("esp", "esp"),
("ah", "ah"),
("ah-esp", "ah-esp")]
self.fields['transform_protocol'].choices = transform_protocol_choices
class Meta(object):
name = _("Add New IPSec Policy")
permissions = ('openstack.services.network',)
help_text_template = 'project/vpn/_add_ipsec_policy_help.html'
class AddIPSecPolicyStep(workflows.Step):
action_class = AddIPSecPolicyAction
contributes = ("name", "description", "auth_algorithm",
"encapsulation_mode", "encryption_algorithm",
"lifetime_units", "lifetime_value",
"pfs", "transform_protocol")
def contribute(self, data, context):
context = super(AddIPSecPolicyStep, self).contribute(data, context)
context['lifetime'] = {'units': data['lifetime_units'],
'value': data['lifetime_value']}
context.pop('lifetime_units')
context.pop('lifetime_value')
if data:
return context
class AddIPSecPolicy(workflows.Workflow):
slug = "addipsecpolicy"
name = _("Add IPSec Policy")
finalize_button_name = _("Add")
success_message = _('Added IPSec Policy "%s".')
failure_message = _('Unable to add IPSec Policy "%s".')
success_url = "horizon:project:vpn:index"
default_steps = (AddIPSecPolicyStep,)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_vpn.ipsecpolicy_create(request, **context)
return True
except Exception:
return False
class AddIPSecSiteConnectionAction(workflows.Action):
name = forms.CharField(max_length=80, label=_("Name"), required=False)
description = forms.CharField(
initial="", required=False,
max_length=80, label=_("Description"))
vpnservice_id = forms.ChoiceField(
label=_("VPN Service associated with this connection"))
ikepolicy_id = forms.ChoiceField(
label=_("IKE Policy associated with this connection"))
ipsecpolicy_id = forms.ChoiceField(
label=_("IPSec Policy associated with this connection"))
peer_address = forms.IPField(
label=_("Peer gateway public IPv4/IPv6 Address or FQDN"),
help_text=_("Peer gateway public IPv4/IPv6 address or FQDN for "
"the VPN Connection"),
version=forms.IPv4 | forms.IPv6,
mask=False)
peer_id = forms.IPField(
label=_("Peer router identity for authentication (Peer ID)"),
help_text=_("Peer router identity for authentication. "
"Can be IPv4/IPv6 address, e-mail, key ID, or FQDN"),
version=forms.IPv4 | forms.IPv6,
mask=False)
peer_cidrs = forms.MultiIPField(
label=_("Remote peer subnet(s)"),
help_text=_("Remote peer subnet(s) address(es) "
"with mask(s) in CIDR format "
"separated with commas if needed "
"(e.g. 20.1.0.0/24, 21.1.0.0/24)"),
version=forms.IPv4 | forms.IPv6,
mask=True)
psk = forms.CharField(
max_length=80,
label=_("Pre-Shared Key (PSK) string"),
widget=forms.PasswordInput(render_value=False),
help_text=_("The pre-defined key string "
"between the two peers of the VPN connection"))
def populate_ikepolicy_id_choices(self, request, context):
ikepolicy_id_choices = [('', _("Select IKE Policy"))]
try:
tenant_id = self.request.user.tenant_id
ikepolicies = api_vpn.ikepolicy_list(request, tenant_id=tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve IKE Policies list.'))
ikepolicies = []
for p in ikepolicies:
ikepolicy_id_choices.append((p.id, p.name))
self.fields['ikepolicy_id'].choices = ikepolicy_id_choices
return ikepolicy_id_choices
def populate_ipsecpolicy_id_choices(self, request, context):
ipsecpolicy_id_choices = [('', _("Select IPSec Policy"))]
try:
tenant_id = self.request.user.tenant_id
ipsecpolicies = api_vpn.ipsecpolicy_list(request,
tenant_id=tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve IPSec Policies list.'))
ipsecpolicies = []
for p in ipsecpolicies:
ipsecpolicy_id_choices.append((p.id, p.name))
self.fields['ipsecpolicy_id'].choices = ipsecpolicy_id_choices
return ipsecpolicy_id_choices
def populate_vpnservice_id_choices(self, request, context):
vpnservice_id_choices = [('', _("Select VPN Service"))]
try:
tenant_id = self.request.user.tenant_id
vpnservices = api_vpn.vpnservice_list(request, tenant_id=tenant_id)
except Exception:
exceptions.handle(request,
_('Unable to retrieve VPN Services list.'))
vpnservices = []
for s in vpnservices:
vpnservice_id_choices.append((s.id, s.name))
self.fields['vpnservice_id'].choices = vpnservice_id_choices
return vpnservice_id_choices
class Meta(object):
name = _("Add New IPSec Site Connection")
permissions = ('openstack.services.network',)
help_text = _("Create IPSec Site Connection for current "
"project. Assign a name and description for the "
"IPSec Site Connection. "
"All fields in this tab are required."
)
class AddIPSecSiteConnectionStep(workflows.Step):
action_class = AddIPSecSiteConnectionAction
contributes = ("name", "description",
"vpnservice_id", "ikepolicy_id", "ipsecpolicy_id",
"peer_address", "peer_id", "peer_cidrs", "psk")
class AddIPSecSiteConnectionOptionalAction(workflows.Action):
mtu = forms.IntegerField(
min_value=68,
label=_("Maximum Transmission Unit size for the connection"),
initial=1500,
required=False,
help_text=_("Equal to or greater than 68 if the local subnet is IPv4. "
"Equal to or greater than 1280 if the local subnet "
"is IPv6."))
dpd_action = forms.ChoiceField(label=_("Dead peer detection actions"),
required=False)
dpd_interval = forms.IntegerField(
min_value=1, label=_("Dead peer detection interval"),
initial=30,
required=False,
help_text=_("Valid integer lesser than DPD timeout"))
dpd_timeout = forms.IntegerField(
min_value=1, label=_("Dead peer detection timeout"),
initial=120,
required=False,
help_text=_("Valid integer greater than the DPD interval"))
initiator = forms.ChoiceField(label=_("Initiator state"), required=False)
admin_state_up = forms.BooleanField(
label=_("Enable Admin State"),
help_text=_("The state of IPSec site connection to start in. "
"If disabled (not checked), IPSec site connection "
"does not forward packets."),
initial=True,
required=False)
def __init__(self, request, *args, **kwargs):
super(AddIPSecSiteConnectionOptionalAction, self).__init__(
request, *args, **kwargs)
initiator_choices = [("bi-directional", "bi-directional"),
("response-only", "response-only")]
self.fields['initiator'].choices = initiator_choices
def populate_dpd_action_choices(self, request, context):
dpd_action_choices = [("hold", "hold"),
("clear", "clear"),
("disabled", "disabled"),
("restart", "restart"),
("restart-by-peer", "restart-by-peer")]
self.fields['dpd_action'].choices = dpd_action_choices
return dpd_action_choices
def clean(self):
cleaned_data = super(AddIPSecSiteConnectionOptionalAction,
self).clean()
interval = cleaned_data.get('dpd_interval')
timeout = cleaned_data.get('dpd_timeout')
if not interval < timeout:
msg = _("DPD Timeout must be greater than DPD Interval")
self._errors['dpd_timeout'] = self.error_class([msg])
return cleaned_data
class Meta(object):
name = _("Optional Parameters")
permissions = ('openstack.services.network',)
help_text = _("Fields in this tab are optional. "
"You can configure the detail of "
"IPSec site connection created."
)
class AddIPSecSiteConnectionOptionalStep(workflows.Step):
action_class = AddIPSecSiteConnectionOptionalAction
contributes = ("dpd_action", "dpd_interval", "dpd_timeout",
"initiator", "mtu", "admin_state_up")
def contribute(self, data, context):
context = super(
AddIPSecSiteConnectionOptionalStep, self).contribute(data, context)
context['dpd'] = {'action': data['dpd_action'],
'interval': data['dpd_interval'],
'timeout': data['dpd_timeout']}
context.pop('dpd_action')
context.pop('dpd_interval')
context.pop('dpd_timeout')
cidrs = context['peer_cidrs']
context['peer_cidrs'] = cidrs.replace(" ", "").split(",")
if data:
return context
class AddIPSecSiteConnection(workflows.Workflow):
slug = "addipsecsiteconnection"
name = _("Add IPSec Site Connection")
finalize_button_name = _("Add")
success_message = _('Added IPSec Site Connection "%s".')
failure_message = _('Unable to add IPSec Site Connection "%s".')
success_url = "horizon:project:vpn:index"
default_steps = (AddIPSecSiteConnectionStep,
AddIPSecSiteConnectionOptionalStep)
def format_status_message(self, message):
return message % self.context.get('name')
def handle(self, request, context):
try:
api_vpn.ipsecsiteconnection_create(request, **context)
return True
except Exception:
return False

View File

@ -0,0 +1,23 @@
# 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.
# The slug of the panel to be added to HORIZON_CONFIG. Required.
PANEL = 'vpn'
# The slug of the dashboard the PANEL associated with. Required.
PANEL_DASHBOARD = 'project'
# The slug of the panel group the PANEL is associated with.
PANEL_GROUP = 'network'
# Python panel class of the PANEL to be added.
ADD_PANEL = 'neutron_vpnaas_dashboard.dashboards.project.panel.VPN'
ADD_INSTALLED_APPS = ["neutron_vpnaas_dashboard"]

7
requirements.txt Normal file
View File

@ -0,0 +1,7 @@
# The order of packages is significant, because pip processes them in the order
# of appearance. Changing the order has an impact on the overall integration
# process, which may cause wedges in the gate later.
pbr!=2.1.0,>=2.0.0 # Apache-2.0
Django<1.10,>=1.8 # BSD
python-neutronclient>=5.1.0 # Apache-2.0

32
setup.cfg Normal file
View File

@ -0,0 +1,32 @@
[metadata]
name = neutron-vpnaas-dashboard
summary = Neutron VPNaaS Dashboard
description-file =
README.rst
author = OpenStack
author-email = openstack-dev@lists.openstack.org
home-page = http://docs.openstack.org/developer/trove/
classifier =
Environment :: OpenStack
Intended Audience :: Information Technology
Intended Audience :: System Administrators
License :: OSI Approved :: Apache Software License
Operating System :: POSIX :: Linux
Programming Language :: Python
Programming Language :: Python :: 2
Programming Language :: Python :: 2.7
Programming Language :: Python :: 3
Programming Language :: Python :: 3.5
[files]
packages =
neutron_vpnaas_dashboard
[build_sphinx]
source-dir = doc/source
build-dir = doc/build
all-files = 1
warning-is-error = 1
[upload_sphinx]
upload-dir = doc/build/html

29
setup.py Normal file
View File

@ -0,0 +1,29 @@
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
#
# 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.
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
import setuptools
# In python < 2.7.4, a lazy loading of package `pbr` will break
# setuptools if some other modules registered functions in `atexit`.
# solution from: http://bugs.python.org/issue15881#msg170215
try:
import multiprocessing # noqa
except ImportError:
pass
setuptools.setup(
setup_requires=['pbr>=2.0.0'],
pbr=True)